<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<link href="common/css/sf.css" rel="stylesheet" type="text/css"/>
<title>PE: 部分求值</title>
</head>
<link href="common/jquery-ui/jquery-ui.css" rel="stylesheet">
<script src="common/jquery-ui/external/jquery/jquery.js"></script>
<script src="common/jquery-ui/jquery-ui.js"></script>
<script src="common/toggleproofs.js"></script>
<link href="common/css/plf.css" rel="stylesheet" type="text/css"/>

<body>

<div id="page">

<div id="header">
<a href='https://coq-zh.github.io/SF-zh/index.html'>
<img src='common/media/image/sf_logo_sm.png'></a>
</br><a href='index.html'>  <span class='booktitleinheader'>Volume 2: 编程语言基础</span><br></br>
<ul id='menu'>
   <a href='toc.html'><li class='section_name'>目录</li></a>
   <a href='coqindex.html'><li class='section_name'>索引</li></a>
   <a href='deps.html'><li class='section_name'>路线</li></a>
</ul>
</a></div>

<div id="main">

<h1 class="libtitle">PE<span class="subtitle">部分求值</span></h1>


<div class="code code-tight">

<span class="comment">(*&nbsp;本章由單中杰（Chung-chieh&nbsp;Shan）撰写和维护。*)</span><br/>
</div>

<div class="doc">
<a href="Equiv.html"><span class="inlineref">Equiv</span></a> 一章介绍了常量折叠作为程序变换的一个例子，并证明了此变换保持了程序的语义。
    常量折叠变换适用于明显的常量上，例如 <span class="inlinecode"><span class="id" type="var">ANum</span></span> 表达式。比如说，它将命令 <span class="inlinecode"><span class="id" type="var">Y</span></span> <span class="inlinecode"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span></span> <span class="inlinecode">3</span> <span class="inlinecode">+</span> <span class="inlinecode">1</span>
    化简为 <span class="inlinecode"><span class="id" type="var">Y</span></span> <span class="inlinecode"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span></span> <span class="inlinecode">4</span>。然而它并不会顺着数据流传播已知的常量。例如，它无法化简如下的
    语句序列

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;3;;&nbsp;<span class="id" type="var">Y</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;<span class="id" type="var">X</span>&nbsp;+&nbsp;1
<div class="paragraph"> </div>

</div>
    为

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;3;;&nbsp;<span class="id" type="var">Y</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;4
<div class="paragraph"> </div>

</div>
    因为当其运行到 <span class="inlinecode"><span class="id" type="var">Y</span></span> 的时候并不知道 <span class="inlinecode"><span class="id" type="var">X</span></span> 是 <span class="inlinecode">3</span>。

<div class="paragraph"> </div>

    我们自然想要改进常量折叠，使其可以传播已知的常量并使用他们化简程序。
    这样做便得到了<b>部分求值（partial evaluation）</b>的初级形式。我们将会看到，
    部分求值之所以被这样形容是因为看起来它像在运行程序，但只有部分程序会被求值，
    因为程序只有一部分输入是已知的。比如，在不知道 <span class="inlinecode"><span class="id" type="var">Y</span></span> 的初始值的情况下，我们仅能把

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;3;;&nbsp;<span class="id" type="var">Y</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;(<span class="id" type="var">X</span>&nbsp;+&nbsp;1)&nbsp;-&nbsp;<span class="id" type="var">Y</span>
<div class="paragraph"> </div>

</div>
    化简到

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;3;;&nbsp;<span class="id" type="var">Y</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;4&nbsp;-&nbsp;<span class="id" type="var">Y</span>
<div class="paragraph"> </div>

</div>

</div>
<div class="code code-tight">

<span class="id" type="var">From</span> <span class="id" type="var">PLF</span> <span class="id" type="keyword">Require</span> <span class="id" type="keyword">Import</span> <span class="id" type="var">Maps</span>.<br/>
<span class="id" type="var">From</span> <span class="id" type="var">Coq</span> <span class="id" type="keyword">Require</span> <span class="id" type="keyword">Import</span> <span class="id" type="var">Bool.Bool</span>.<br/>
<span class="id" type="var">From</span> <span class="id" type="var">Coq</span> <span class="id" type="keyword">Require</span> <span class="id" type="keyword">Import</span> <span class="id" type="var">Arith.Arith</span>.<br/>
<span class="id" type="var">From</span> <span class="id" type="var">Coq</span> <span class="id" type="keyword">Require</span> <span class="id" type="keyword">Import</span> <span class="id" type="var">Arith.EqNat</span>.<br/>
<span class="id" type="var">From</span> <span class="id" type="var">Coq</span> <span class="id" type="keyword">Require</span> <span class="id" type="keyword">Import</span> <span class="id" type="var">Arith.PeanoNat</span>. <span class="id" type="keyword">Import</span> <span class="id" type="var">Nat</span>.<br/>
<span class="id" type="var">From</span> <span class="id" type="var">Coq</span> <span class="id" type="keyword">Require</span> <span class="id" type="keyword">Import</span> <span class="id" type="var">omega.Omega</span>.<br/>
<span class="id" type="var">From</span> <span class="id" type="var">Coq</span> <span class="id" type="keyword">Require</span> <span class="id" type="keyword">Import</span> <span class="id" type="var">Logic.FunctionalExtensionality</span>.<br/>
<span class="id" type="var">From</span> <span class="id" type="var">Coq</span> <span class="id" type="keyword">Require</span> <span class="id" type="keyword">Import</span> <span class="id" type="var">Lists.List</span>.<br/>
<span class="id" type="keyword">Import</span> <span class="id" type="var">ListNotations</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="var">From</span> <span class="id" type="var">PLF</span> <span class="id" type="keyword">Require</span> <span class="id" type="keyword">Import</span> <span class="id" type="var">Smallstep</span>.<br/>
<span class="id" type="var">From</span> <span class="id" type="var">PLF</span> <span class="id" type="keyword">Require</span> <span class="id" type="keyword">Import</span> <span class="id" type="var">Imp</span>.<br/>
</div>

<div class="doc">
<a name="lab576"></a><h1 class="section">一般化的常量折叠</h1>

<div class="paragraph"> </div>

 作为开始，首先需要确定如何表达状态的部分事实。例如在上面的例子中，部分求值器会知道
    在两个赋值语句中间时 <span class="inlinecode"><span class="id" type="var">X</span></span> 是 <span class="inlinecode">3</span>，但不知道关于其他变量的任何信息。 
<div class="paragraph"> </div>

<a name="lab577"></a><h2 class="section">部分状态</h2>

<div class="paragraph"> </div>

 从概念上讲，我们可以认为部分状态（partial state）的类型是 <span class="inlinecode"><span class="id" type="var">string</span></span> <span class="inlinecode">→</span> <span class="inlinecode"><span class="id" type="var">option</span></span> <span class="inlinecode"><span class="id" type="var">nat</span></span>
    (相反全状态的类型是 <span class="inlinecode"><span class="id" type="var">string</span></span> <span class="inlinecode">→</span> <span class="inlinecode"><span class="id" type="var">nat</span></span>）。然而，除了对部分状态中的变量进行查询和更新以外，
    我们还想要比较两个部分状态，得到其不同的之处，并处理条件控制流。
    由于无法对两个任意的函数进行比较，因此我们更具体地把部分状态表示为由
    <span class="inlinecode"><span class="id" type="var">string</span></span> <span class="inlinecode">*</span> <span class="inlinecode"><span class="id" type="var">nat</span></span> 序对构成的列表。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Definition</span> <span class="id" type="var">pe_state</span> := <span class="id" type="var">list</span> (<span class="id" type="var">string</span> * <span class="id" type="var">nat</span>).<br/>
</div>

<div class="doc">
一个（类型为 <span class="inlinecode"><span class="id" type="var">string</span></span> 的）变量出现在列表中当且仅当我们知道其当前的 <span class="inlinecode"><span class="id" type="var">nat</span></span> 值。
    <span class="inlinecode"><span class="id" type="var">pe_lookup</span></span> 函数实现了这个功能的具体表示。（如果变量名在列表中出现了多次，
    那么我们仅使用第一个，但我们会定义部分求值器使其不会构造出这样的 <span class="inlinecode"><span class="id" type="var">pe_state</span></span>。）
</div>
<div class="code code-tight">

<span class="id" type="keyword">Fixpoint</span> <span class="id" type="var">pe_lookup</span> (<span class="id" type="var">pe_st</span> : <span class="id" type="var">pe_state</span>) (<span class="id" type="var">V</span>:<span class="id" type="var">string</span>) : <span class="id" type="var">option</span> <span class="id" type="var">nat</span> :=<br/>
&nbsp;&nbsp;<span class="id" type="keyword">match</span> <span class="id" type="var">pe_st</span> <span class="id" type="keyword">with</span><br/>
&nbsp;&nbsp;| [] ⇒ <span class="id" type="var">None</span><br/>
&nbsp;&nbsp;| (<span class="id" type="var">V'</span>,<span class="id" type="var">n'</span>)::<span class="id" type="var">pe_st</span> ⇒ <span class="id" type="keyword">if</span> <span class="id" type="var">eqb_string</span> <span class="id" type="var">V</span> <span class="id" type="var">V'</span> <span class="id" type="keyword">then</span> <span class="id" type="var">Some</span> <span class="id" type="var">n'</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">else</span> <span class="id" type="var">pe_lookup</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">V</span><br/>
&nbsp;&nbsp;<span class="id" type="keyword">end</span>.<br/>
</div>

<div class="doc">
比如，<span class="inlinecode"><span class="id" type="var">empty_pe_state</span></span> 表示空状态——一个将任何标识符都映射到 <span class="inlinecode"><span class="id" type="var">None</span></span> 的函数。 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Definition</span> <span class="id" type="var">empty_pe_state</span> : <span class="id" type="var">pe_state</span> := [].<br/>
</div>

<div class="doc">
更一般地，如果这个 <span class="inlinecode"><span class="id" type="var">list</span></span> 表示的 <span class="inlinecode"><span class="id" type="var">pe_state</span></span> 不含有某个标识符，那么此 <span class="inlinecode"><span class="id" type="var">pe_state</span></span>
    必将这个标识符映射到 <span class="inlinecode"><span class="id" type="var">None</span></span>。在证明这一点之前，我们首先定义一个策略来帮助我们对
    字符串的等价关系进行推理。策略

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">compare</span>&nbsp;<span class="id" type="var">V</span>&nbsp;<span class="id" type="var">V'</span>
<div class="paragraph"> </div>

</div>
    用于对 <span class="inlinecode"><span class="id" type="var">eqb_string</span></span> <span class="inlinecode"><span class="id" type="var">V</span></span> <span class="inlinecode"><span class="id" type="var">V'</span></span> 的分类情形进行推理。
    当 <span class="inlinecode"><span class="id" type="var">V</span></span> <span class="inlinecode">=</span> <span class="inlinecode"><span class="id" type="var">V'</span></span> 时，此策略将全部的 <span class="inlinecode"><span class="id" type="var">V</span></span> 替换为 <span class="inlinecode"><span class="id" type="var">V'</span></span>。 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Tactic Notation</span> "compare" <span class="id" type="var">ident</span>(<span class="id" type="var">i</span>) <span class="id" type="var">ident</span>(<span class="id" type="var">j</span>) :=<br/>
&nbsp;&nbsp;<span class="id" type="keyword">let</span> <span class="id" type="var">H</span> := <span class="id" type="tactic">fresh</span> "Heq" <span class="id" type="var">i</span> <span class="id" type="var">j</span> <span class="id" type="keyword">in</span><br/>
&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">eqb_stringP</span> <span class="id" type="var">i</span> <span class="id" type="var">j</span>);<br/>
&nbsp;&nbsp;[ <span class="id" type="tactic">subst</span> <span class="id" type="var">j</span> | ].<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">pe_domain</span>: <span style='font-size:120%;'>&forall;</span><span class="id" type="var">pe_st</span> <span class="id" type="var">V</span> <span class="id" type="var">n</span>,<br/>
&nbsp;&nbsp;<span class="id" type="var">pe_lookup</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">V</span> = <span class="id" type="var">Some</span> <span class="id" type="var">n</span> →<br/>
&nbsp;&nbsp;<span class="id" type="var">In</span> <span class="id" type="var">V</span> (<span class="id" type="var">map</span> (@<span class="id" type="var">fst</span> <span class="id" type="var">_</span> <span class="id" type="var">_</span>) <span class="id" type="var">pe_st</span>).<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">V</span> <span class="id" type="var">n</span> <span class="id" type="var">H</span>. <span class="id" type="tactic">induction</span> <span class="id" type="var">pe_st</span> <span class="id" type="keyword">as</span> [| [<span class="id" type="var">V'</span> <span class="id" type="var">n'</span>] <span class="id" type="var">pe_st</span>].<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;<span class="inlinecode"></span>&nbsp;*)</span> <span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;::&nbsp;*)</span> <span class="id" type="tactic">simpl</span> <span class="id" type="keyword">in</span> <span class="id" type="var">H</span>. <span class="id" type="tactic">simpl</span>. <span class="id" type="var">compare</span> <span class="id" type="var">V</span> <span class="id" type="var">V'</span>; <span class="id" type="tactic">auto</span>. <span class="id" type="keyword">Qed</span>.<br/>
</div>

<div class="doc">
接下来，我们会大量使用标准库和 <span class="inlinecode"><span class="id" type="var">Logic.v</span></span> 中定义的 <span class="inlinecode"><span class="id" type="var">In</span></span> 性质： 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Print</span> <span class="id" type="var">In</span>.<br/>
<span class="comment">(*&nbsp;===&gt;&nbsp;Fixpoint&nbsp;In&nbsp;{A:Type}&nbsp;(a:&nbsp;A)&nbsp;(l:list&nbsp;A)&nbsp;:&nbsp;Prop&nbsp;:=<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;match&nbsp;l&nbsp;with<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;<span class="inlinecode"></span>&nbsp;=&gt;&nbsp;False<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;b&nbsp;::&nbsp;m&nbsp;=&gt;&nbsp;b&nbsp;=&nbsp;a&nbsp;\/&nbsp;In&nbsp;a&nbsp;m<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;forall&nbsp;A&nbsp;:&nbsp;Type,&nbsp;A&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;list&nbsp;A&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;Prop&nbsp;*)</span><br/>
</div>

<div class="doc">
除了我们之前学习过的关于 <span class="inlinecode"><span class="id" type="var">In</span></span> 的众多引理，下面这个也会非常有用： 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Check</span> <span class="id" type="var">filter_In</span>.<br/>
<span class="comment">(*&nbsp;===&gt;&nbsp;filter_In&nbsp;:&nbsp;forall&nbsp;(A&nbsp;:&nbsp;Type)&nbsp;(f&nbsp;:&nbsp;A&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;bool)&nbsp;(x&nbsp;:&nbsp;A)&nbsp;(l&nbsp;:&nbsp;list&nbsp;A),<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;In&nbsp;x&nbsp;(filter&nbsp;f&nbsp;l)&nbsp;&lt;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;In&nbsp;x&nbsp;l&nbsp;/\&nbsp;f&nbsp;x&nbsp;=&nbsp;true&nbsp;&nbsp;*)</span><br/>
</div>

<div class="doc">
如果类型 <span class="inlinecode"><span class="id" type="var">A</span></span> 有操作符 <span class="inlinecode"><span class="id" type="var">eqb</span></span> 用于测试其元素的相等关系，我们可以计算一个布尔值 <span class="inlinecode"><span class="id" type="var">inb</span></span> <span class="inlinecode"><span class="id" type="var">eqb</span></span> <span class="inlinecode"><span class="id" type="var">a</span></span> <span class="inlinecode"><span class="id" type="var">l</span></span>
    用于测试 <span class="inlinecode"><span class="id" type="var">In</span></span> <span class="inlinecode"><span class="id" type="var">a</span></span> <span class="inlinecode"><span class="id" type="var">l</span></span> 是否成立。 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Fixpoint</span> <span class="id" type="var">inb</span> {<span class="id" type="var">A</span> : <span class="id" type="keyword">Type</span>} (<span class="id" type="var">eqb</span> : <span class="id" type="var">A</span> → <span class="id" type="var">A</span> → <span class="id" type="var">bool</span>) (<span class="id" type="var">a</span> : <span class="id" type="var">A</span>) (<span class="id" type="var">l</span> : <span class="id" type="var">list</span> <span class="id" type="var">A</span>) :=<br/>
&nbsp;&nbsp;<span class="id" type="keyword">match</span> <span class="id" type="var">l</span> <span class="id" type="keyword">with</span><br/>
&nbsp;&nbsp;| [] ⇒ <span class="id" type="var">false</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">a'</span>::<span class="id" type="var">l'</span> ⇒ <span class="id" type="var">eqb</span> <span class="id" type="var">a</span> <span class="id" type="var">a'</span> || <span class="id" type="var">inb</span> <span class="id" type="var">eqb</span> <span class="id" type="var">a</span> <span class="id" type="var">l'</span><br/>
&nbsp;&nbsp;<span class="id" type="keyword">end</span>.<br/>
</div>

<div class="doc">
容易使用 <span class="inlinecode"><span class="id" type="var">reflect</span></span> 性质关联起 <span class="inlinecode"><span class="id" type="var">inb</span></span> 和 <span class="inlinecode"><span class="id" type="var">In</span></span>： 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Lemma</span> <span class="id" type="var">inbP</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">A</span> : <span class="id" type="keyword">Type</span>, <span style='font-size:120%;'>&forall;</span><span class="id" type="var">eqb</span> : <span class="id" type="var">A</span>→<span class="id" type="var">A</span>→<span class="id" type="var">bool</span>,<br/>
&nbsp;&nbsp;(<span style='font-size:120%;'>&forall;</span><span class="id" type="var">a<sub>1</sub></span> <span class="id" type="var">a<sub>2</sub></span>, <span class="id" type="var">reflect</span> (<span class="id" type="var">a<sub>1</sub></span> = <span class="id" type="var">a<sub>2</sub></span>) (<span class="id" type="var">eqb</span> <span class="id" type="var">a<sub>1</sub></span> <span class="id" type="var">a<sub>2</sub></span>)) →<br/>
&nbsp;&nbsp;<span style='font-size:120%;'>&forall;</span><span class="id" type="var">a</span> <span class="id" type="var">l</span>, <span class="id" type="var">reflect</span> (<span class="id" type="var">In</span> <span class="id" type="var">a</span> <span class="id" type="var">l</span>) (<span class="id" type="var">inb</span> <span class="id" type="var">eqb</span> <span class="id" type="var">a</span> <span class="id" type="var">l</span>).<br/>
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">A</span> <span class="id" type="var">eqb</span> <span class="id" type="var">beqP</span> <span class="id" type="var">a</span> <span class="id" type="var">l</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">induction</span> <span class="id" type="var">l</span> <span class="id" type="keyword">as</span> [|<span class="id" type="var">a'</span> <span class="id" type="var">l'</span> <span class="id" type="var">IH</span>].<br/>
&nbsp;&nbsp;- <span class="id" type="var">constructor</span>. <span class="id" type="tactic">intros</span> [].<br/>
&nbsp;&nbsp;- <span class="id" type="tactic">simpl</span>. <span class="id" type="tactic">destruct</span> (<span class="id" type="var">beqP</span> <span class="id" type="var">a</span> <span class="id" type="var">a'</span>).<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="id" type="tactic">subst</span>. <span class="id" type="var">constructor</span>. <span class="id" type="var">left</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="id" type="tactic">simpl</span>. <span class="id" type="tactic">destruct</span> <span class="id" type="var">IH</span>; <span class="id" type="var">constructor</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* <span class="id" type="var">right</span>. <span class="id" type="tactic">trivial</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* <span class="id" type="tactic">intros</span> [<span class="id" type="var">H<sub>1</sub></span> | <span class="id" type="var">H<sub>2</sub></span>]; <span class="id" type="tactic">congruence</span>.<br/>
<span class="id" type="keyword">Qed</span>.<br/>
</div>

<div class="doc">
<a name="lab578"></a><h2 class="section">算术表达式</h2>

<div class="paragraph"> </div>

 对 <span class="inlinecode"><span class="id" type="var">aexp</span></span> 的部分求值是简单的——它基本上和常量折叠 <span class="inlinecode"><span class="id" type="var">fold_constants_aexp</span></span> 相同，
    除了有时候部分状态可以告诉我们变量对应的值，我们便可以用一个常量替换这个变量。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Fixpoint</span> <span class="id" type="var">pe_aexp</span> (<span class="id" type="var">pe_st</span> : <span class="id" type="var">pe_state</span>) (<span class="id" type="var">a</span> : <span class="id" type="var">aexp</span>) : <span class="id" type="var">aexp</span> :=<br/>
&nbsp;&nbsp;<span class="id" type="keyword">match</span> <span class="id" type="var">a</span> <span class="id" type="keyword">with</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">ANum</span> <span class="id" type="var">n</span> ⇒ <span class="id" type="var">ANum</span> <span class="id" type="var">n</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">AId</span> <span class="id" type="var">i</span> ⇒ <span class="id" type="keyword">match</span> <span class="id" type="var">pe_lookup</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">i</span> <span class="id" type="keyword">with</span> <span class="comment">(*&nbsp;&lt;-----&nbsp;新添加的&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| <span class="id" type="var">Some</span> <span class="id" type="var">n</span> ⇒ <span class="id" type="var">ANum</span> <span class="id" type="var">n</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| <span class="id" type="var">None</span> ⇒ <span class="id" type="var">AId</span> <span class="id" type="var">i</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">end</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">APlus</span> <span class="id" type="var">a<sub>1</sub></span> <span class="id" type="var">a<sub>2</sub></span> ⇒<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">match</span> (<span class="id" type="var">pe_aexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">a<sub>1</sub></span>, <span class="id" type="var">pe_aexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">a<sub>2</sub></span>) <span class="id" type="keyword">with</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| (<span class="id" type="var">ANum</span> <span class="id" type="var">n<sub>1</sub></span>, <span class="id" type="var">ANum</span> <span class="id" type="var">n<sub>2</sub></span>) ⇒ <span class="id" type="var">ANum</span> (<span class="id" type="var">n<sub>1</sub></span> + <span class="id" type="var">n<sub>2</sub></span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| (<span class="id" type="var">a<sub>1</sub>'</span>, <span class="id" type="var">a<sub>2</sub>'</span>) ⇒ <span class="id" type="var">APlus</span> <span class="id" type="var">a<sub>1</sub>'</span> <span class="id" type="var">a<sub>2</sub>'</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">end</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">AMinus</span> <span class="id" type="var">a<sub>1</sub></span> <span class="id" type="var">a<sub>2</sub></span> ⇒<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">match</span> (<span class="id" type="var">pe_aexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">a<sub>1</sub></span>, <span class="id" type="var">pe_aexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">a<sub>2</sub></span>) <span class="id" type="keyword">with</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| (<span class="id" type="var">ANum</span> <span class="id" type="var">n<sub>1</sub></span>, <span class="id" type="var">ANum</span> <span class="id" type="var">n<sub>2</sub></span>) ⇒ <span class="id" type="var">ANum</span> (<span class="id" type="var">n<sub>1</sub></span> - <span class="id" type="var">n<sub>2</sub></span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| (<span class="id" type="var">a<sub>1</sub>'</span>, <span class="id" type="var">a<sub>2</sub>'</span>) ⇒ <span class="id" type="var">AMinus</span> <span class="id" type="var">a<sub>1</sub>'</span> <span class="id" type="var">a<sub>2</sub>'</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">end</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">AMult</span> <span class="id" type="var">a<sub>1</sub></span> <span class="id" type="var">a<sub>2</sub></span> ⇒<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">match</span> (<span class="id" type="var">pe_aexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">a<sub>1</sub></span>, <span class="id" type="var">pe_aexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">a<sub>2</sub></span>) <span class="id" type="keyword">with</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| (<span class="id" type="var">ANum</span> <span class="id" type="var">n<sub>1</sub></span>, <span class="id" type="var">ANum</span> <span class="id" type="var">n<sub>2</sub></span>) ⇒ <span class="id" type="var">ANum</span> (<span class="id" type="var">n<sub>1</sub></span> * <span class="id" type="var">n<sub>2</sub></span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| (<span class="id" type="var">a<sub>1</sub>'</span>, <span class="id" type="var">a<sub>2</sub>'</span>) ⇒ <span class="id" type="var">AMult</span> <span class="id" type="var">a<sub>1</sub>'</span> <span class="id" type="var">a<sub>2</sub>'</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">end</span><br/>
&nbsp;&nbsp;<span class="id" type="keyword">end</span>.<br/>
</div>

<div class="doc">
部分求值器会折叠起常量，但并不会应用加法的结合律。 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Example</span> <span class="id" type="var">test_pe_aexp1</span>:<br/>
&nbsp;&nbsp;<span class="id" type="var">pe_aexp</span> [(<span class="id" type="var">X</span>,3)] (<span class="id" type="var">X</span> + 1 + <span class="id" type="var">Y</span>)%<span class="id" type="var">imp</span><br/>
&nbsp;&nbsp;= (4 + <span class="id" type="var">Y</span>)%<span class="id" type="var">imp</span>.<br/>
<div class="togglescript" id="proofcontrol1" onclick="toggleDisplay('proof1');toggleDisplay('proofcontrol1')"><span class="show"></span></div>
<div class="proofscript" id="proof1" onclick="toggleDisplay('proof1');toggleDisplay('proofcontrol1')">
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">reflexivity</span>. <span class="id" type="keyword">Qed</span>.<br/>
</div>

<br/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">text_pe_aexp2</span>:<br/>
&nbsp;&nbsp;<span class="id" type="var">pe_aexp</span> [(<span class="id" type="var">Y</span>,3)] (<span class="id" type="var">X</span> + 1 + <span class="id" type="var">Y</span>)%<span class="id" type="var">imp</span><br/>
&nbsp;&nbsp;= (<span class="id" type="var">X</span> + 1 + 3)%<span class="id" type="var">imp</span>.<br/>
<div class="togglescript" id="proofcontrol2" onclick="toggleDisplay('proof2');toggleDisplay('proofcontrol2')"><span class="show"></span></div>
<div class="proofscript" id="proof2" onclick="toggleDisplay('proof2');toggleDisplay('proofcontrol2')">
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">reflexivity</span>. <span class="id" type="keyword">Qed</span>.<br/>
</div>
</div>

<div class="doc">
现在，<span class="inlinecode"><span class="id" type="var">pe_aexp</span></span> 在什么意义上是正确的呢？可以合理地将 <span class="inlinecode"><span class="id" type="var">pe_aexp</span></span> 的正确性
    定义为：若一个全状态 <span class="inlinecode"><span class="id" type="var">st</span>:<span class="id" type="var">state</span></span> 与部分状态 <span class="inlinecode"><span class="id" type="var">pe_st</span>:<span class="id" type="var">pe_state</span></span> 是相容的
    （换句话说，<span class="inlinecode"><span class="id" type="var">pe_st</span></span> 中每个变量的值同 <span class="inlinecode"><span class="id" type="var">st</span></span> 中这个变量的值相同），那么在 <span class="inlinecode"><span class="id" type="var">st</span></span>
    状态中对 <span class="inlinecode"><span class="id" type="var">a</span></span> 求值和对 <span class="inlinecode"><span class="id" type="var">pe_aexp</span></span> <span class="inlinecode"><span class="id" type="var">pe_st</span></span> <span class="inlinecode"><span class="id" type="var">a</span></span> 求值会产生相同结果。这个陈述确实是真的。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Definition</span> <span class="id" type="var">pe_consistent</span> (<span class="id" type="var">st</span>:<span class="id" type="var">state</span>) (<span class="id" type="var">pe_st</span>:<span class="id" type="var">pe_state</span>) :=<br/>
&nbsp;&nbsp;<span style='font-size:120%;'>&forall;</span><span class="id" type="var">V</span> <span class="id" type="var">n</span>, <span class="id" type="var">Some</span> <span class="id" type="var">n</span> = <span class="id" type="var">pe_lookup</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">V</span> → <span class="id" type="var">st</span> <span class="id" type="var">V</span> = <span class="id" type="var">n</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">pe_aexp_correct_weak</span>: <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">pe_st</span>, <span class="id" type="var">pe_consistent</span> <span class="id" type="var">st</span> <span class="id" type="var">pe_st</span> →<br/>
&nbsp;&nbsp;<span style='font-size:120%;'>&forall;</span><span class="id" type="var">a</span>, <span class="id" type="var">aeval</span> <span class="id" type="var">st</span> <span class="id" type="var">a</span> = <span class="id" type="var">aeval</span> <span class="id" type="var">st</span> (<span class="id" type="var">pe_aexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">a</span>).<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">unfold</span> <span class="id" type="var">pe_consistent</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">st</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">H</span> <span class="id" type="var">a</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">induction</span> <span class="id" type="var">a</span>; <span class="id" type="tactic">simpl</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">try</span> <span class="id" type="tactic">reflexivity</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">try</span> (<span class="id" type="tactic">destruct</span> (<span class="id" type="var">pe_aexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">a<sub>1</sub></span>);<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">pe_aexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">a<sub>2</sub></span>);<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> <span class="id" type="var">IHa1</span>; <span class="id" type="tactic">rewrite</span> <span class="id" type="var">IHa2</span>; <span class="id" type="tactic">reflexivity</span>).<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;同&nbsp;fold_constants_aexp_sound&nbsp;比较，唯一不同的分类是&nbsp;AId。&nbsp;*)</span><br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;AId&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">remember</span> (<span class="id" type="var">pe_lookup</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">x</span>) <span class="id" type="keyword">as</span> <span class="id" type="var">l</span>. <span class="id" type="tactic">destruct</span> <span class="id" type="var">l</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;Some&nbsp;*)</span> <span class="id" type="tactic">rewrite</span> <span class="id" type="var">H</span> <span class="id" type="keyword">with</span> (<span class="id" type="var">n</span>:=<span class="id" type="var">n</span>) <span class="id" type="tactic">by</span> <span class="id" type="tactic">apply</span> <span class="id" type="var">Heql</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;None&nbsp;*)</span> <span class="id" type="tactic">reflexivity</span>.<br/>
<span class="id" type="keyword">Qed</span>.<br/>
</div>

<div class="doc">
然而，我们很快就会希望这个部分求值器可以移除掉赋值语句。比如说，它会将

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;3;;&nbsp;<span class="id" type="var">Y</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;<span class="id" type="var">X</span>&nbsp;-&nbsp;<span class="id" type="var">Y</span>;;&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;4
<div class="paragraph"> </div>

</div>
    简化为

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Y</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;3&nbsp;-&nbsp;<span class="id" type="var">Y</span>;;&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;4
<div class="paragraph"> </div>

</div>
    它保留了最后对 <span class="inlinecode"><span class="id" type="var">X</span></span> 的赋值语句。为了完成这种简化，我们需要部分求值的结果

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">pe_aexp</span>&nbsp;[(<span class="id" type="var">X</span>,3)]&nbsp;(<span class="id" type="var">X</span>&nbsp;-&nbsp;<span class="id" type="var">Y</span>)
<div class="paragraph"> </div>

</div>
    等于 <span class="inlinecode">3</span> <span class="inlinecode">-</span> <span class="inlinecode"><span class="id" type="var">Y</span></span> 而_非_原始的表达式 <span class="inlinecode"><span class="id" type="var">X</span></span> <span class="inlinecode">-<span class="id" type="var">Y</span></span>。毕竟，若将

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;3;;&nbsp;<span class="id" type="var">Y</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;<span class="id" type="var">X</span>&nbsp;-&nbsp;<span class="id" type="var">Y</span>;;&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;4
<div class="paragraph"> </div>

</div>
    变换为

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Y</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;<span class="id" type="var">X</span>&nbsp;-&nbsp;<span class="id" type="var">Y</span>;;&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;4
<div class="paragraph"> </div>

</div>
    就不仅仅是低效的，而是不正确的结果了，尽管结果表达式 <span class="inlinecode">3</span> <span class="inlinecode">-</span> <span class="inlinecode"><span class="id" type="var">Y</span></span> 和 <span class="inlinecode"><span class="id" type="var">X</span></span> <span class="inlinecode">-</span> <span class="inlinecode"><span class="id" type="var">Y</span></span>
    都满足我们上面证明的正确性条件。确实，如果我们只是定义 <span class="inlinecode"><span class="id" type="var">pe_aexp</span></span> <span class="inlinecode"><span class="id" type="var">pt_st</span></span> <span class="inlinecode"><span class="id" type="var">a</span></span> <span class="inlinecode">=</span> <span class="inlinecode"><span class="id" type="var">a</span></span>
    那么定理 <span class="inlinecode"><span class="id" type="var">pe_aexp_correct_weak</span></span> 也会直接成立。

<div class="paragraph"> </div>

    但是，我们想要证明关于 <span class="inlinecode"><span class="id" type="var">pe_aexp</span></span> 更强的正确性：对部分求值产生的表达式进行求值
    （<span class="inlinecode"><span class="id" type="var">aeval</span></span> <span class="inlinecode"><span class="id" type="var">st</span></span> <span class="inlinecode">(<span class="id" type="var">pe_aexp</span></span> <span class="inlinecode"><span class="id" type="var">pe_st</span></span> <span class="inlinecode"><span class="id" type="var">a</span>)</span>） 必须不依赖全状态 <span class="inlinecode"><span class="id" type="var">st</span></span> 中已经被部分状态
    <span class="inlinecode"><span class="id" type="var">pe_st</span></span> 所指明的部分。为了精确地表达，让我们定义一个函数 <span class="inlinecode"><span class="id" type="var">pe_override</span></span>，
    它使用 <span class="inlinecode"><span class="id" type="var">pe_st</span></span> 中的内容更新 <span class="inlinecode"><span class="id" type="var">st</span></span>。换句话说，<span class="inlinecode"><span class="id" type="var">pe_override</span></span> 将 <span class="inlinecode"><span class="id" type="var">pe_st</span></span>
    中的赋值语句置于 <span class="inlinecode"><span class="id" type="var">st</span></span> 之上。 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Fixpoint</span> <span class="id" type="var">pe_update</span> (<span class="id" type="var">st</span>:<span class="id" type="var">state</span>) (<span class="id" type="var">pe_st</span>:<span class="id" type="var">pe_state</span>) : <span class="id" type="var">state</span> :=<br/>
&nbsp;&nbsp;<span class="id" type="keyword">match</span> <span class="id" type="var">pe_st</span> <span class="id" type="keyword">with</span><br/>
&nbsp;&nbsp;| [] ⇒ <span class="id" type="var">st</span><br/>
&nbsp;&nbsp;| (<span class="id" type="var">V</span>,<span class="id" type="var">n</span>)::<span class="id" type="var">pe_st</span> ⇒ <span class="id" type="var">t_update</span> (<span class="id" type="var">pe_update</span> <span class="id" type="var">st</span> <span class="id" type="var">pe_st</span>) <span class="id" type="var">V</span> <span class="id" type="var">n</span><br/>
&nbsp;&nbsp;<span class="id" type="keyword">end</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">test_pe_update</span>:<br/>
&nbsp;&nbsp;<span class="id" type="var">pe_update</span> (<span class="id" type="var">Y</span> !<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> 1) [(<span class="id" type="var">X</span>,3);(<span class="id" type="var">Z</span>,2)]<br/>
&nbsp;&nbsp;= (<span class="id" type="var">X</span> !<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> 3 ; <span class="id" type="var">Z</span> !<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> 2 ; <span class="id" type="var">Y</span> !<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> 1).<br/>
<div class="togglescript" id="proofcontrol3" onclick="toggleDisplay('proof3');toggleDisplay('proofcontrol3')"><span class="show"></span></div>
<div class="proofscript" id="proof3" onclick="toggleDisplay('proof3');toggleDisplay('proofcontrol3')">
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">reflexivity</span>. <span class="id" type="keyword">Qed</span>.<br/>
</div>
</div>

<div class="doc">
尽管 <span class="inlinecode"><span class="id" type="var">pe_update</span></span> 对一个具体的 <span class="inlinecode"><span class="id" type="var">list</span></span> 表示的 <span class="inlinecode"><span class="id" type="var">pe_state</span></span> 进行操作，它的行为完全
    由 <span class="inlinecode"><span class="id" type="var">pe_lookup</span></span> 对 <span class="inlinecode"><span class="id" type="var">pe_state</span></span> 的解释所定义。 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Theorem</span> <span class="id" type="var">pe_update_correct</span>: <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">V<sub>0</sub></span>,<br/>
&nbsp;&nbsp;<span class="id" type="var">pe_update</span> <span class="id" type="var">st</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">V<sub>0</sub></span> =<br/>
&nbsp;&nbsp;<span class="id" type="keyword">match</span> <span class="id" type="var">pe_lookup</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">V<sub>0</sub></span> <span class="id" type="keyword">with</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">Some</span> <span class="id" type="var">n</span> ⇒ <span class="id" type="var">n</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">None</span> ⇒ <span class="id" type="var">st</span> <span class="id" type="var">V<sub>0</sub></span><br/>
&nbsp;&nbsp;<span class="id" type="keyword">end</span>.<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">intros</span>. <span class="id" type="tactic">induction</span> <span class="id" type="var">pe_st</span> <span class="id" type="keyword">as</span> [| [<span class="id" type="var">V</span> <span class="id" type="var">n</span>] <span class="id" type="var">pe_st</span>]. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">simpl</span> <span class="id" type="keyword">in</span> *. <span class="id" type="tactic">unfold</span> <span class="id" type="var">t_update</span>.<br/>
&nbsp;&nbsp;<span class="id" type="var">compare</span> <span class="id" type="var">V<sub>0</sub></span> <span class="id" type="var">V</span>; <span class="id" type="tactic">auto</span>. <span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">eqb_string_refl</span>; <span class="id" type="tactic">auto</span>. <span class="id" type="tactic">rewrite</span> <span class="id" type="var">false_eqb_string</span>; <span class="id" type="tactic">auto</span>. <span class="id" type="keyword">Qed</span>.<br/>
</div>

<div class="doc">
我们可以以两种方式关联起 <span class="inlinecode"><span class="id" type="var">pe_consistent</span></span> 和 <span class="inlinecode"><span class="id" type="var">pe_update</span></span>。
    首先，用部分状态覆写一个状态总是会得到同这个部分状态相容的状态。
    第二，如果一个状态本身同某个部分状态相容，那么用这个部分状态覆写
    这个状态会得到相同的状态。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Theorem</span> <span class="id" type="var">pe_update_consistent</span>: <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">pe_st</span>,<br/>
&nbsp;&nbsp;<span class="id" type="var">pe_consistent</span> (<span class="id" type="var">pe_update</span> <span class="id" type="var">st</span> <span class="id" type="var">pe_st</span>) <span class="id" type="var">pe_st</span>.<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">st</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">V</span> <span class="id" type="var">n</span> <span class="id" type="var">H</span>. <span class="id" type="tactic">rewrite</span> <span class="id" type="var">pe_update_correct</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">pe_lookup</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">V</span>); <span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span>. <span class="id" type="tactic">reflexivity</span>. <span class="id" type="keyword">Qed</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">pe_consistent_update</span>: <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">pe_st</span>,<br/>
&nbsp;&nbsp;<span class="id" type="var">pe_consistent</span> <span class="id" type="var">st</span> <span class="id" type="var">pe_st</span> → <span style='font-size:120%;'>&forall;</span><span class="id" type="var">V</span>, <span class="id" type="var">st</span> <span class="id" type="var">V</span> = <span class="id" type="var">pe_update</span> <span class="id" type="var">st</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">V</span>.<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">st</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">H</span> <span class="id" type="var">V</span>. <span class="id" type="tactic">rewrite</span> <span class="id" type="var">pe_update_correct</span>.<br/>
&nbsp;&nbsp;<span class="id" type="var">remember</span> (<span class="id" type="var">pe_lookup</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">V</span>) <span class="id" type="keyword">as</span> <span class="id" type="var">l</span>. <span class="id" type="tactic">destruct</span> <span class="id" type="var">l</span>; <span class="id" type="tactic">auto</span>. <span class="id" type="keyword">Qed</span>.<br/>
</div>

<div class="doc">
现在我们可以表述和证明 <span class="inlinecode"><span class="id" type="var">pe_aexp</span></span> 更强的正确性，这会帮助我们定义接下来的部分求值器。

<div class="paragraph"> </div>

    直观地讲，使用部分求值来运行程序由两个阶段构成。第一个为<b>静态</b>阶段（static stage），
    我们在部分状态下对程序进行部分求值，并得到一个<b>剩余</b>程序（residual program）。
    第二个为<b>动态</b>阶段（dynamic stage），我们在动态状态中对剩余程序进行求值。
    这个动态状态提供了在静态（部分）状态中未知的变量的值。因此，剩余程序应当等价于
    对原始程序<b>预添加（prepending）</b>上部分状态中的赋值语句。 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Theorem</span> <span class="id" type="var">pe_aexp_correct</span>: <span style='font-size:120%;'>&forall;</span>(<span class="id" type="var">pe_st</span>:<span class="id" type="var">pe_state</span>) (<span class="id" type="var">a</span>:<span class="id" type="var">aexp</span>) (<span class="id" type="var">st</span>:<span class="id" type="var">state</span>),<br/>
&nbsp;&nbsp;<span class="id" type="var">aeval</span> (<span class="id" type="var">pe_update</span> <span class="id" type="var">st</span> <span class="id" type="var">pe_st</span>) <span class="id" type="var">a</span> = <span class="id" type="var">aeval</span> <span class="id" type="var">st</span> (<span class="id" type="var">pe_aexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">a</span>).<br/>
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">a</span> <span class="id" type="var">st</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">induction</span> <span class="id" type="var">a</span>; <span class="id" type="tactic">simpl</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">try</span> <span class="id" type="tactic">reflexivity</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">try</span> (<span class="id" type="tactic">destruct</span> (<span class="id" type="var">pe_aexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">a<sub>1</sub></span>);<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">pe_aexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">a<sub>2</sub></span>);<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> <span class="id" type="var">IHa1</span>; <span class="id" type="tactic">rewrite</span> <span class="id" type="var">IHa2</span>; <span class="id" type="tactic">reflexivity</span>).<br/>
&nbsp;&nbsp;<span class="comment">(*&nbsp;同&nbsp;fold_constants_aexp_sound&nbsp;比较，唯一不同的分类是&nbsp;AId。&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> <span class="id" type="var">pe_update_correct</span>. <span class="id" type="tactic">destruct</span> (<span class="id" type="var">pe_lookup</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">x</span>); <span class="id" type="tactic">reflexivity</span>.<br/>
<span class="id" type="keyword">Qed</span>.<br/>
</div>

<div class="doc">
<a name="lab579"></a><h2 class="section">布尔表达式</h2>

<div class="paragraph"> </div>

 对布尔表达式的部分求值是相似的。事实上，它完全类似于对布尔表达式常量折叠，
    因为我们的语言中并没有布尔值的变量。 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Fixpoint</span> <span class="id" type="var">pe_bexp</span> (<span class="id" type="var">pe_st</span> : <span class="id" type="var">pe_state</span>) (<span class="id" type="var">b</span> : <span class="id" type="var">bexp</span>) : <span class="id" type="var">bexp</span> :=<br/>
&nbsp;&nbsp;<span class="id" type="keyword">match</span> <span class="id" type="var">b</span> <span class="id" type="keyword">with</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">BTrue</span>        ⇒ <span class="id" type="var">BTrue</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">BFalse</span>       ⇒ <span class="id" type="var">BFalse</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">BEq</span> <span class="id" type="var">a<sub>1</sub></span> <span class="id" type="var">a<sub>2</sub></span> ⇒<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">match</span> (<span class="id" type="var">pe_aexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">a<sub>1</sub></span>, <span class="id" type="var">pe_aexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">a<sub>2</sub></span>) <span class="id" type="keyword">with</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| (<span class="id" type="var">ANum</span> <span class="id" type="var">n<sub>1</sub></span>, <span class="id" type="var">ANum</span> <span class="id" type="var">n<sub>2</sub></span>) ⇒ <span class="id" type="keyword">if</span> <span class="id" type="var">n<sub>1</sub></span> =? <span class="id" type="var">n<sub>2</sub></span> <span class="id" type="keyword">then</span> <span class="id" type="var">BTrue</span> <span class="id" type="keyword">else</span> <span class="id" type="var">BFalse</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| (<span class="id" type="var">a<sub>1</sub>'</span>, <span class="id" type="var">a<sub>2</sub>'</span>) ⇒ <span class="id" type="var">BEq</span> <span class="id" type="var">a<sub>1</sub>'</span> <span class="id" type="var">a<sub>2</sub>'</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">end</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">BLe</span> <span class="id" type="var">a<sub>1</sub></span> <span class="id" type="var">a<sub>2</sub></span> ⇒<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">match</span> (<span class="id" type="var">pe_aexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">a<sub>1</sub></span>, <span class="id" type="var">pe_aexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">a<sub>2</sub></span>) <span class="id" type="keyword">with</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| (<span class="id" type="var">ANum</span> <span class="id" type="var">n<sub>1</sub></span>, <span class="id" type="var">ANum</span> <span class="id" type="var">n<sub>2</sub></span>) ⇒ <span class="id" type="keyword">if</span> <span class="id" type="var">n<sub>1</sub></span> &lt;=? <span class="id" type="var">n<sub>2</sub></span> <span class="id" type="keyword">then</span> <span class="id" type="var">BTrue</span> <span class="id" type="keyword">else</span> <span class="id" type="var">BFalse</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| (<span class="id" type="var">a<sub>1</sub>'</span>, <span class="id" type="var">a<sub>2</sub>'</span>) ⇒ <span class="id" type="var">BLe</span> <span class="id" type="var">a<sub>1</sub>'</span> <span class="id" type="var">a<sub>2</sub>'</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">end</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">BNot</span> <span class="id" type="var">b<sub>1</sub></span> ⇒<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">match</span> (<span class="id" type="var">pe_bexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">b<sub>1</sub></span>) <span class="id" type="keyword">with</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| <span class="id" type="var">BTrue</span> ⇒ <span class="id" type="var">BFalse</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| <span class="id" type="var">BFalse</span> ⇒ <span class="id" type="var">BTrue</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| <span class="id" type="var">b<sub>1</sub>'</span> ⇒ <span class="id" type="var">BNot</span> <span class="id" type="var">b<sub>1</sub>'</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">end</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">BAnd</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">b<sub>2</sub></span> ⇒<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">match</span> (<span class="id" type="var">pe_bexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">b<sub>1</sub></span>, <span class="id" type="var">pe_bexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">b<sub>2</sub></span>) <span class="id" type="keyword">with</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| (<span class="id" type="var">BTrue</span>, <span class="id" type="var">BTrue</span>) ⇒ <span class="id" type="var">BTrue</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| (<span class="id" type="var">BTrue</span>, <span class="id" type="var">BFalse</span>) ⇒ <span class="id" type="var">BFalse</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| (<span class="id" type="var">BFalse</span>, <span class="id" type="var">BTrue</span>) ⇒ <span class="id" type="var">BFalse</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| (<span class="id" type="var">BFalse</span>, <span class="id" type="var">BFalse</span>) ⇒ <span class="id" type="var">BFalse</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| (<span class="id" type="var">b<sub>1</sub>'</span>, <span class="id" type="var">b<sub>2</sub>'</span>) ⇒ <span class="id" type="var">BAnd</span> <span class="id" type="var">b<sub>1</sub>'</span> <span class="id" type="var">b<sub>2</sub>'</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">end</span><br/>
&nbsp;&nbsp;<span class="id" type="keyword">end</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">test_pe_bexp1</span>:<br/>
&nbsp;&nbsp;<span class="id" type="var">pe_bexp</span> [(<span class="id" type="var">X</span>,3)] (~(<span class="id" type="var">X</span> ≤ 3))%<span class="id" type="var">imp</span><br/>
&nbsp;&nbsp;= <span class="id" type="var">false</span>.<br/>
<div class="togglescript" id="proofcontrol4" onclick="toggleDisplay('proof4');toggleDisplay('proofcontrol4')"><span class="show"></span></div>
<div class="proofscript" id="proof4" onclick="toggleDisplay('proof4');toggleDisplay('proofcontrol4')">
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">reflexivity</span>. <span class="id" type="keyword">Qed</span>.<br/>
</div>

<br/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">test_pe_bexp2</span>: <span style='font-size:120%;'>&forall;</span><span class="id" type="var">b</span>:<span class="id" type="var">bexp</span>,<br/>
&nbsp;&nbsp;<span class="id" type="var">b</span> = (~(<span class="id" type="var">X</span> ≤ (<span class="id" type="var">X</span> + 1)))%<span class="id" type="var">imp</span> →<br/>
&nbsp;&nbsp;<span class="id" type="var">pe_bexp</span> [] <span class="id" type="var">b</span> = <span class="id" type="var">b</span>.<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">b</span> <span class="id" type="var">H</span>. <span class="id" type="tactic">rewrite</span> → <span class="id" type="var">H</span>. <span class="id" type="tactic">reflexivity</span>. <span class="id" type="keyword">Qed</span>.<br/>
</div>

<div class="doc">
<span class="inlinecode"><span class="id" type="var">pe_bexp</span></span> 的正确性和上面 <span class="inlinecode"><span class="id" type="var">pe_aexp</span></span> 的正确性类似。 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Theorem</span> <span class="id" type="var">pe_bexp_correct</span>: <span style='font-size:120%;'>&forall;</span>(<span class="id" type="var">pe_st</span>:<span class="id" type="var">pe_state</span>) (<span class="id" type="var">b</span>:<span class="id" type="var">bexp</span>) (<span class="id" type="var">st</span>:<span class="id" type="var">state</span>),<br/>
&nbsp;&nbsp;<span class="id" type="var">beval</span> (<span class="id" type="var">pe_update</span> <span class="id" type="var">st</span> <span class="id" type="var">pe_st</span>) <span class="id" type="var">b</span> = <span class="id" type="var">beval</span> <span class="id" type="var">st</span> (<span class="id" type="var">pe_bexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">b</span>).<br/>
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">b</span> <span class="id" type="var">st</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">induction</span> <span class="id" type="var">b</span>; <span class="id" type="tactic">simpl</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">try</span> <span class="id" type="tactic">reflexivity</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">try</span> (<span class="id" type="var">remember</span> (<span class="id" type="var">pe_aexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">a<sub>1</sub></span>) <span class="id" type="keyword">as</span> <span class="id" type="var">a<sub>1</sub>'</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">remember</span> (<span class="id" type="var">pe_aexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">a<sub>2</sub></span>) <span class="id" type="keyword">as</span> <span class="id" type="var">a<sub>2</sub>'</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">assert</span> (<span class="id" type="var">H<sub>1</sub></span>: <span class="id" type="var">aeval</span> (<span class="id" type="var">pe_update</span> <span class="id" type="var">st</span> <span class="id" type="var">pe_st</span>) <span class="id" type="var">a<sub>1</sub></span> = <span class="id" type="var">aeval</span> <span class="id" type="var">st</span> <span class="id" type="var">a<sub>1</sub>'</span>);<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">assert</span> (<span class="id" type="var">H<sub>2</sub></span>: <span class="id" type="var">aeval</span> (<span class="id" type="var">pe_update</span> <span class="id" type="var">st</span> <span class="id" type="var">pe_st</span>) <span class="id" type="var">a<sub>2</sub></span> = <span class="id" type="var">aeval</span> <span class="id" type="var">st</span> <span class="id" type="var">a<sub>2</sub>'</span>);<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">try</span> (<span class="id" type="tactic">subst</span>; <span class="id" type="tactic">apply</span> <span class="id" type="var">pe_aexp_correct</span>);<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> <span class="id" type="var">a<sub>1</sub>'</span>; <span class="id" type="tactic">destruct</span> <span class="id" type="var">a<sub>2</sub>'</span>; <span class="id" type="tactic">rewrite</span> <span class="id" type="var">H<sub>1</sub></span>; <span class="id" type="tactic">rewrite</span> <span class="id" type="var">H<sub>2</sub></span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">simpl</span>; <span class="id" type="tactic">try</span> <span class="id" type="tactic">destruct</span> (<span class="id" type="var">n</span> =? <span class="id" type="var">n<sub>0</sub></span>);<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">try</span> <span class="id" type="tactic">destruct</span> (<span class="id" type="var">n</span> &lt;=? <span class="id" type="var">n<sub>0</sub></span>); <span class="id" type="tactic">reflexivity</span>);<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">try</span> (<span class="id" type="tactic">destruct</span> (<span class="id" type="var">pe_bexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">b</span>); <span class="id" type="tactic">rewrite</span> <span class="id" type="var">IHb</span>; <span class="id" type="tactic">reflexivity</span>);<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">try</span> (<span class="id" type="tactic">destruct</span> (<span class="id" type="var">pe_bexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">b<sub>1</sub></span>);<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">pe_bexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">b<sub>2</sub></span>);<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> <span class="id" type="var">IHb1</span>; <span class="id" type="tactic">rewrite</span> <span class="id" type="var">IHb2</span>; <span class="id" type="tactic">reflexivity</span>).<br/>
<span class="id" type="keyword">Qed</span>.<br/>
</div>

<div class="doc">
<a name="lab580"></a><h1 class="section">无循环命令的部分求值</h1>

<div class="paragraph"> </div>

 接下来如何处理对命令的部分求值呢？部分求值和完全求值之间的类比仍然适用：
    对命令的完全求值将初始状态转换为最终的状态，而对命令的部分求值将初始状态转换为
    最终的部分状态。不过，由于状态是局部的，一些命令可能无法在静态阶段执行。
    因此，正如同 <span class="inlinecode"><span class="id" type="var">pe_aexp</span></span> 返回一个 <span class="inlinecode"><span class="id" type="var">aexp</span></span> 的剩余表达式、<span class="inlinecode"><span class="id" type="var">pe_bexp</span></span> 返回一个
    <span class="inlinecode"><span class="id" type="var">bexp</span></span> 的剩余表达式，对命令的部分求值也产生剩余命令。

<div class="paragraph"> </div>

    另一个部分求值和完全求值相似的地方是它不会对所有命令都停机。构造出一个
    部分求值器使其对所有的命令都停机并不是困难的；困难在于所构造的部分求值器
    在停机的同时还能自动地执行想要的优化，例如循环展开。如果我们有意把
    源程序以一种更容易区分出静态阶段和动态阶段的方式写出，那么部分求值器
    常常可以停机并执行更多优化。这种方式被称作<b>绑定时间改进（binding-time
    improvement）</b>。变量的绑定时间告诉我们何时可以知道它的值——“静态”或“动态”。

<div class="paragraph"> </div>

    不管怎样，我们现在先接受这样的事实，即这个部分求值器不会是一个从源程序
    和初始状态到剩余程序和最终部分状态的全函数。为了对这种非停机性建模，我们
    采用和命令的完全求值相同的技术，即归纳地定义关系。我们写下

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">c<sub>1</sub></span>&nbsp;/&nbsp;<span class="id" type="var">st</span>&nbsp;\\&nbsp;<span class="id" type="var">c<sub>1</sub>'</span>&nbsp;/&nbsp;<span class="id" type="var">st'</span>
<div class="paragraph"> </div>

</div>
    意思是对源程序 <span class="inlinecode"><span class="id" type="var">c<sub>1</sub></span></span> 在初始状态 <span class="inlinecode"><span class="id" type="var">st</span></span> 中部分求值产生剩余程序 <span class="inlinecode"><span class="id" type="var">c<sub>1</sub>'</span></span>
    和最终部分状态 <span class="inlinecode"><span class="id" type="var">st'</span></span>。举个例子，我们想要让

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[]&nbsp;/&nbsp;(<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;3&nbsp;;;&nbsp;<span class="id" type="var">Y</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;<span class="id" type="var">Z</span>&nbsp;*&nbsp;(<span class="id" type="var">X</span>&nbsp;+&nbsp;<span class="id" type="var">X</span>))&nbsp;\\&nbsp;(<span class="id" type="var">Y</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;<span class="id" type="var">Z</span>&nbsp;*&nbsp;6)&nbsp;/&nbsp;[(<span class="id" type="var">X</span>,3)]
<div class="paragraph"> </div>

</div>
    成立。对 <span class="inlinecode"><span class="id" type="var">X</span></span> 的赋值出现在最终部分状态中，而非剩余命令中。

<div class="paragraph"> </div>

    （写成 <span class="inlinecode"><span class="id" type="var">st</span></span> <span class="inlinecode">=[</span> <span class="inlinecode"><span class="id" type="var">c<sub>1</sub></span></span> <span class="inlinecode">]⇒</span> <span class="inlinecode"><span class="id" type="var">c<sub>1</sub>'</span></span> <span class="inlinecode">/</span> <span class="inlinecode"><span class="id" type="var">st'</span></span> 的形式会更接近于 <a href="Imp.html"><span class="inlineref">Imp</span></a> 使用的记法，
    或许这里需要改一下！）

<div class="paragraph"> </div>

<a name="lab581"></a><h2 class="section">赋值</h2>

<div class="paragraph"> </div>

 让我们首先考虑对赋值语句的部分求值。上面源程序中的两个赋值语句需要区别对待。
    第一个赋值 <span class="inlinecode"><span class="id" type="var">X</span></span> <span class="inlinecode"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span></span> <span class="inlinecode">3</span> 是<b>静态的</b>：它的右值是一个常量（更一般地讲，可以
    简化为常量），因此我们需要更新部分状态中的 <span class="inlinecode"><span class="id" type="var">X</span></span> 为 <span class="inlinecode">3</span>，而不产生剩余代码。
    （实际上，我们产生了剩余程序 <span class="inlinecode"><span class="id" type="var">SKIP</span></span>。）第二个赋值 <span class="inlinecode"><span class="id" type="var">Y</span></span> <span class="inlinecode"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span></span> <span class="inlinecode"><span class="id" type="var">Z</span></span> <span class="inlinecode">*</span> <span class="inlinecode">(<span class="id" type="var">X</span></span> <span class="inlinecode">+</span> <span class="inlinecode"><span class="id" type="var">X</span>)</span>
    是<b>动态的</b>：它的右值无法被简化为常量，因此我们应当将它保留在剩余程序
    中，并且若 <span class="inlinecode"><span class="id" type="var">Y</span></span> 出现在部分状态中，则应当被移除。为了实现这两个情形，我们定
    义函数 <span class="inlinecode"><span class="id" type="var">pe_add</span></span> 和 <span class="inlinecode"><span class="id" type="var">pe_remove</span></span>。与 <span class="inlinecode"><span class="id" type="var">pe_update</span></span> 类似，这些函数操作
    某个具体的 <span class="inlinecode"><span class="id" type="var">list</span></span> 表示的 <span class="inlinecode"><span class="id" type="var">pe_state</span></span>，但定理 <span class="inlinecode"><span class="id" type="var">pe_add_correct</span></span> 和
    <span class="inlinecode"><span class="id" type="var">pe_remove_correct</span></span> 通过 <span class="inlinecode"><span class="id" type="var">pe_lookup</span></span> 对 <span class="inlinecode"><span class="id" type="var">pe_state</span></span> 的解释定义了
    他们的行为。 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Fixpoint</span> <span class="id" type="var">pe_remove</span> (<span class="id" type="var">pe_st</span>:<span class="id" type="var">pe_state</span>) (<span class="id" type="var">V</span>:<span class="id" type="var">string</span>) : <span class="id" type="var">pe_state</span> :=<br/>
&nbsp;&nbsp;<span class="id" type="keyword">match</span> <span class="id" type="var">pe_st</span> <span class="id" type="keyword">with</span><br/>
&nbsp;&nbsp;| [] ⇒ []<br/>
&nbsp;&nbsp;| (<span class="id" type="var">V'</span>,<span class="id" type="var">n'</span>)::<span class="id" type="var">pe_st</span> ⇒ <span class="id" type="keyword">if</span> <span class="id" type="var">eqb_string</span> <span class="id" type="var">V</span> <span class="id" type="var">V'</span> <span class="id" type="keyword">then</span> <span class="id" type="var">pe_remove</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">V</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">else</span> (<span class="id" type="var">V'</span>,<span class="id" type="var">n'</span>) :: <span class="id" type="var">pe_remove</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">V</span><br/>
&nbsp;&nbsp;<span class="id" type="keyword">end</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">pe_remove_correct</span>: <span style='font-size:120%;'>&forall;</span><span class="id" type="var">pe_st</span> <span class="id" type="var">V</span> <span class="id" type="var">V<sub>0</sub></span>,<br/>
&nbsp;&nbsp;<span class="id" type="var">pe_lookup</span> (<span class="id" type="var">pe_remove</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">V</span>) <span class="id" type="var">V<sub>0</sub></span><br/>
&nbsp;&nbsp;= <span class="id" type="keyword">if</span> <span class="id" type="var">eqb_string</span> <span class="id" type="var">V</span> <span class="id" type="var">V<sub>0</sub></span> <span class="id" type="keyword">then</span> <span class="id" type="var">None</span> <span class="id" type="keyword">else</span> <span class="id" type="var">pe_lookup</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">V<sub>0</sub></span>.<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">V</span> <span class="id" type="var">V<sub>0</sub></span>. <span class="id" type="tactic">induction</span> <span class="id" type="var">pe_st</span> <span class="id" type="keyword">as</span> [| [<span class="id" type="var">V'</span> <span class="id" type="var">n'</span>] <span class="id" type="var">pe_st</span>].<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;<span class="inlinecode"></span>&nbsp;*)</span> <span class="id" type="tactic">destruct</span> (<span class="id" type="var">eqb_string</span> <span class="id" type="var">V</span> <span class="id" type="var">V<sub>0</sub></span>); <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;::&nbsp;*)</span> <span class="id" type="tactic">simpl</span>. <span class="id" type="var">compare</span> <span class="id" type="var">V</span> <span class="id" type="var">V'</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;相等&nbsp;*)</span> <span class="id" type="tactic">rewrite</span> <span class="id" type="var">IHpe_st</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">eqb_stringP</span> <span class="id" type="var">V</span> <span class="id" type="var">V<sub>0</sub></span>). <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> <span class="id" type="var">false_eqb_string</span>; <span class="id" type="tactic">auto</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;不相等&nbsp;*)</span> <span class="id" type="tactic">simpl</span>. <span class="id" type="var">compare</span> <span class="id" type="var">V<sub>0</sub></span> <span class="id" type="var">V'</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* <span class="comment">(*&nbsp;相等&nbsp;*)</span> <span class="id" type="tactic">rewrite</span> <span class="id" type="var">false_eqb_string</span>; <span class="id" type="tactic">auto</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* <span class="comment">(*&nbsp;不相等&nbsp;*)</span> <span class="id" type="tactic">rewrite</span> <span class="id" type="var">IHpe_st</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
<span class="id" type="keyword">Qed</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Definition</span> <span class="id" type="var">pe_add</span> (<span class="id" type="var">pe_st</span>:<span class="id" type="var">pe_state</span>) (<span class="id" type="var">V</span>:<span class="id" type="var">string</span>) (<span class="id" type="var">n</span>:<span class="id" type="var">nat</span>) : <span class="id" type="var">pe_state</span> :=<br/>
&nbsp;&nbsp;(<span class="id" type="var">V</span>,<span class="id" type="var">n</span>) :: <span class="id" type="var">pe_remove</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">V</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">pe_add_correct</span>: <span style='font-size:120%;'>&forall;</span><span class="id" type="var">pe_st</span> <span class="id" type="var">V</span> <span class="id" type="var">n</span> <span class="id" type="var">V<sub>0</sub></span>,<br/>
&nbsp;&nbsp;<span class="id" type="var">pe_lookup</span> (<span class="id" type="var">pe_add</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">V</span> <span class="id" type="var">n</span>) <span class="id" type="var">V<sub>0</sub></span><br/>
&nbsp;&nbsp;= <span class="id" type="keyword">if</span> <span class="id" type="var">eqb_string</span> <span class="id" type="var">V</span> <span class="id" type="var">V<sub>0</sub></span> <span class="id" type="keyword">then</span> <span class="id" type="var">Some</span> <span class="id" type="var">n</span> <span class="id" type="keyword">else</span> <span class="id" type="var">pe_lookup</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">V<sub>0</sub></span>.<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">V</span> <span class="id" type="var">n</span> <span class="id" type="var">V<sub>0</sub></span>. <span class="id" type="tactic">unfold</span> <span class="id" type="var">pe_add</span>. <span class="id" type="tactic">simpl</span>.<br/>
&nbsp;&nbsp;<span class="id" type="var">compare</span> <span class="id" type="var">V</span> <span class="id" type="var">V<sub>0</sub></span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;相等&nbsp;*)</span> <span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">eqb_string_refl</span>; <span class="id" type="tactic">auto</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;不相等&nbsp;*)</span> <span class="id" type="tactic">rewrite</span> <span class="id" type="var">pe_remove_correct</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">repeat</span> <span class="id" type="tactic">rewrite</span> <span class="id" type="var">false_eqb_string</span>; <span class="id" type="tactic">auto</span>.<br/>
<span class="id" type="keyword">Qed</span>.<br/>
</div>

<div class="doc">
我们将会用下面的两个定理证明部分求值器正确地处理了动态赋值和静态赋值。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Theorem</span> <span class="id" type="var">pe_update_update_remove</span>: <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">V</span> <span class="id" type="var">n</span>,<br/>
&nbsp;&nbsp;<span class="id" type="var">t_update</span> (<span class="id" type="var">pe_update</span> <span class="id" type="var">st</span> <span class="id" type="var">pe_st</span>) <span class="id" type="var">V</span> <span class="id" type="var">n</span> =<br/>
&nbsp;&nbsp;<span class="id" type="var">pe_update</span> (<span class="id" type="var">t_update</span> <span class="id" type="var">st</span> <span class="id" type="var">V</span> <span class="id" type="var">n</span>) (<span class="id" type="var">pe_remove</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">V</span>).<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">st</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">V</span> <span class="id" type="var">n</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">functional_extensionality</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">V<sub>0</sub></span>. <span class="id" type="tactic">unfold</span> <span class="id" type="var">t_update</span>. <span class="id" type="tactic">rewrite</span> !<span class="id" type="var">pe_update_correct</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> <span class="id" type="var">pe_remove_correct</span>. <span class="id" type="tactic">destruct</span> (<span class="id" type="var">eqb_string</span> <span class="id" type="var">V</span> <span class="id" type="var">V<sub>0</sub></span>); <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;<span class="id" type="keyword">Qed</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">pe_update_update_add</span>: <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">V</span> <span class="id" type="var">n</span>,<br/>
&nbsp;&nbsp;<span class="id" type="var">t_update</span> (<span class="id" type="var">pe_update</span> <span class="id" type="var">st</span> <span class="id" type="var">pe_st</span>) <span class="id" type="var">V</span> <span class="id" type="var">n</span> =<br/>
&nbsp;&nbsp;<span class="id" type="var">pe_update</span> <span class="id" type="var">st</span> (<span class="id" type="var">pe_add</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">V</span> <span class="id" type="var">n</span>).<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">st</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">V</span> <span class="id" type="var">n</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">functional_extensionality</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">V<sub>0</sub></span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">unfold</span> <span class="id" type="var">t_update</span>. <span class="id" type="tactic">rewrite</span> !<span class="id" type="var">pe_update_correct</span>. <span class="id" type="tactic">rewrite</span> <span class="id" type="var">pe_add_correct</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">eqb_string</span> <span class="id" type="var">V</span> <span class="id" type="var">V<sub>0</sub></span>); <span class="id" type="tactic">reflexivity</span>. <span class="id" type="keyword">Qed</span>.<br/>
</div>

<div class="doc">
<a name="lab582"></a><h2 class="section">条件</h2>

<div class="paragraph"> </div>

 比赋值语句的部分求值要麻烦一点的是条件语句 <span class="inlinecode"><span class="id" type="var">TEST</span></span> <span class="inlinecode"><span class="id" type="var">b<sub>1</sub></span></span> <span class="inlinecode"><span class="id" type="var">THEN</span></span> <span class="inlinecode"><span class="id" type="var">c<sub>1</sub></span></span> <span class="inlinecode"><span class="id" type="var">ELSE</span></span> <span class="inlinecode"><span class="id" type="var">c<sub>2</sub></span></span> <span class="inlinecode"><span class="id" type="var">FI</span></span>。
    如果 <span class="inlinecode"><span class="id" type="var">b<sub>1</sub></span></span> 被简化为 <span class="inlinecode"><span class="id" type="var">BTrue</span></span> 或 <span class="inlinecode"><span class="id" type="var">BFalse</span></span>，那么会很容易：我们知道哪个分支
    会被运行。如果 <span class="inlinecode"><span class="id" type="var">b<sub>1</sub></span></span> 不会被简化为常量，那么我们需要对两个分支部分地求值，
    且最终的部分状态在两个分支上可能是不同的！

<div class="paragraph"> </div>

    下面的程序展示了这种困难：

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;3;;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">TEST</span>&nbsp;<span class="id" type="var">Y</span>&nbsp;≤&nbsp;4&nbsp;<span class="id" type="var">THEN</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Y</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;4;;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">TEST</span>&nbsp;<span class="id" type="var">X</span>&nbsp;≤&nbsp;<span class="id" type="var">Y</span>&nbsp;<span class="id" type="var">THEN</span>&nbsp;<span class="id" type="var">Y</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;999&nbsp;<span class="id" type="var">ELSE</span>&nbsp;<span class="id" type="var">SKIP</span>&nbsp;<span class="id" type="var">FI</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">ELSE</span>&nbsp;<span class="id" type="var">SKIP</span>&nbsp;<span class="id" type="var">FI</span>
<div class="paragraph"> </div>

</div>
    假设初始的部分状态为空状态。静态来说，我们不知道 <span class="inlinecode"><span class="id" type="var">Y</span></span> 和 <span class="inlinecode">4</span> 比较的结果，
    因此必须对（外层的）条件语句的两个分支都进行部分求值。在其 <span class="inlinecode"><span class="id" type="var">THEN</span></span>
    分支中，我们知道 <span class="inlinecode"><span class="id" type="var">Y</span></span> 被赋值为 <span class="inlinecode">4</span>，并且可以利用这一点来化简一部分代码。
    在 <span class="inlinecode"><span class="id" type="var">ELSE</span></span> 分支中，到最后我们仍然不知道 <span class="inlinecode"><span class="id" type="var">Y</span></span> 的值会是什么。最终部分状态
    和剩余程序应该是什么呢？

<div class="paragraph"> </div>

    一种处理动态的条件语句的方法是取两个分支上最终部分状态的交。在上面的例子中，
    我们取 <span class="inlinecode">(<span class="id" type="var">Y</span>,4),(<span class="id" type="var">X</span>,3)</span> 和 <span class="inlinecode">(<span class="id" type="var">X</span>,3)</span> 的交，因此最终的部分状态为 <span class="inlinecode">(<span class="id" type="var">X</span>,3)</span>。
    为了抵消丢失掉的对 <span class="inlinecode"><span class="id" type="var">Y</span></span> 的赋值 <span class="inlinecode">4</span>，我们需要在 <span class="inlinecode"><span class="id" type="var">THEN</span></span> 分支的最后添加赋值语句
    <span class="inlinecode"><span class="id" type="var">Y</span></span> <span class="inlinecode"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span></span> <span class="inlinecode">4</span>。因此，剩余程序为

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">SKIP</span>;;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">TEST</span>&nbsp;<span class="id" type="var">Y</span>&nbsp;≤&nbsp;4&nbsp;<span class="id" type="var">THEN</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">SKIP</span>;;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">SKIP</span>;;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Y</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;4<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">ELSE</span>&nbsp;<span class="id" type="var">SKIP</span>&nbsp;<span class="id" type="var">FI</span>
<div class="paragraph"> </div>

</div>
    在 Coq 中编程处理这种情况需要几个辅助函数：我们需要计算两个 <span class="inlinecode"><span class="id" type="var">pe_state</span></span>
    的交（intersection），并将他们的差（difference）转换为一系列的赋值语句。

<div class="paragraph"> </div>

    首先，我们展示如何计算两个 <span class="inlinecode"><span class="id" type="var">pe_state</span></span> 是否对某个变量有不同的值。定理
    <span class="inlinecode"><span class="id" type="var">pe_disagree_domain</span></span> 证明了两个 <span class="inlinecode"><span class="id" type="var">pe_state</span></span> 若对某个变量有不同的值，
    那么此变量必在至少一个状态中出现。 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Definition</span> <span class="id" type="var">pe_disagree_at</span> (<span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span> : <span class="id" type="var">pe_state</span>) (<span class="id" type="var">V</span>:<span class="id" type="var">string</span>) : <span class="id" type="var">bool</span> :=<br/>
&nbsp;&nbsp;<span class="id" type="keyword">match</span> <span class="id" type="var">pe_lookup</span> <span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">V</span>, <span class="id" type="var">pe_lookup</span> <span class="id" type="var">pe_st<sub>2</sub></span> <span class="id" type="var">V</span> <span class="id" type="keyword">with</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">Some</span> <span class="id" type="var">x</span>, <span class="id" type="var">Some</span> <span class="id" type="var">y</span> ⇒ <span class="id" type="var">negb</span> (<span class="id" type="var">x</span> =? <span class="id" type="var">y</span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">None</span>, <span class="id" type="var">None</span> ⇒ <span class="id" type="var">false</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">_</span>, <span class="id" type="var">_</span> ⇒ <span class="id" type="var">true</span><br/>
&nbsp;&nbsp;<span class="id" type="keyword">end</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">pe_disagree_domain</span>: <span style='font-size:120%;'>&forall;</span>(<span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span> : <span class="id" type="var">pe_state</span>) (<span class="id" type="var">V</span>:<span class="id" type="var">string</span>),<br/>
&nbsp;&nbsp;<span class="id" type="var">true</span> = <span class="id" type="var">pe_disagree_at</span> <span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span> <span class="id" type="var">V</span> →<br/>
&nbsp;&nbsp;<span class="id" type="var">In</span> <span class="id" type="var">V</span> (<span class="id" type="var">map</span> (@<span class="id" type="var">fst</span> <span class="id" type="var">_</span> <span class="id" type="var">_</span>) <span class="id" type="var">pe_st<sub>1</sub></span> ++ <span class="id" type="var">map</span> (@<span class="id" type="var">fst</span> <span class="id" type="var">_</span> <span class="id" type="var">_</span>) <span class="id" type="var">pe_st<sub>2</sub></span>).<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">unfold</span> <span class="id" type="var">pe_disagree_at</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span> <span class="id" type="var">V</span> <span class="id" type="var">H</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">in_app_iff</span>.<br/>
&nbsp;&nbsp;<span class="id" type="var">remember</span> (<span class="id" type="var">pe_lookup</span> <span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">V</span>) <span class="id" type="keyword">as</span> <span class="id" type="var">lookup1</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> <span class="id" type="var">lookup1</span> <span class="id" type="keyword">as</span> [<span class="id" type="var">n<sub>1</sub></span>|]. <span class="id" type="var">left</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">pe_domain</span> <span class="id" type="keyword">with</span> <span class="id" type="var">n<sub>1</sub></span>. <span class="id" type="tactic">auto</span>.<br/>
&nbsp;&nbsp;<span class="id" type="var">remember</span> (<span class="id" type="var">pe_lookup</span> <span class="id" type="var">pe_st<sub>2</sub></span> <span class="id" type="var">V</span>) <span class="id" type="keyword">as</span> <span class="id" type="var">lookup2</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> <span class="id" type="var">lookup2</span> <span class="id" type="keyword">as</span> [<span class="id" type="var">n<sub>2</sub></span>|]. <span class="id" type="var">right</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">pe_domain</span> <span class="id" type="keyword">with</span> <span class="id" type="var">n<sub>2</sub></span>. <span class="id" type="tactic">auto</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span>. <span class="id" type="keyword">Qed</span>.<br/>
</div>

<div class="doc">
给定两个 <span class="inlinecode"><span class="id" type="var">pe_state</span></span>，我们定义函数 <span class="inlinecode"><span class="id" type="var">pe_compare</span></span> 用于列出在他们中值不同的变量。
    根据 <span class="inlinecode"><span class="id" type="var">pe_compare_correct</span></span>，列出的变量是精确的：一个变量在列表中当且仅当给定
    的两个 <span class="inlinecode"><span class="id" type="var">pe_state</span></span> 对其有不同的值。进一步地，我们用 <span class="inlinecode"><span class="id" type="var">pe_unique</span></span> 函数来消除
    列表中的重复。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Fixpoint</span> <span class="id" type="var">pe_unique</span> (<span class="id" type="var">l</span> : <span class="id" type="var">list</span> <span class="id" type="var">string</span>) : <span class="id" type="var">list</span> <span class="id" type="var">string</span> :=<br/>
&nbsp;&nbsp;<span class="id" type="keyword">match</span> <span class="id" type="var">l</span> <span class="id" type="keyword">with</span><br/>
&nbsp;&nbsp;| [] ⇒ []<br/>
&nbsp;&nbsp;| <span class="id" type="var">x</span>::<span class="id" type="var">l</span> ⇒<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">x</span> :: <span class="id" type="var">filter</span> (<span class="id" type="keyword">fun</span> <span class="id" type="var">y</span> ⇒ <span class="id" type="keyword">if</span> <span class="id" type="var">eqb_string</span> <span class="id" type="var">x</span> <span class="id" type="var">y</span> <span class="id" type="keyword">then</span> <span class="id" type="var">false</span> <span class="id" type="keyword">else</span> <span class="id" type="var">true</span>) (<span class="id" type="var">pe_unique</span> <span class="id" type="var">l</span>)<br/>
&nbsp;&nbsp;<span class="id" type="keyword">end</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">pe_unique_correct</span>: <span style='font-size:120%;'>&forall;</span><span class="id" type="var">l</span> <span class="id" type="var">x</span>,<br/>
&nbsp;&nbsp;<span class="id" type="var">In</span> <span class="id" type="var">x</span> <span class="id" type="var">l</span> ↔ <span class="id" type="var">In</span> <span class="id" type="var">x</span> (<span class="id" type="var">pe_unique</span> <span class="id" type="var">l</span>).<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">l</span> <span class="id" type="var">x</span>. <span class="id" type="tactic">induction</span> <span class="id" type="var">l</span> <span class="id" type="keyword">as</span> [| <span class="id" type="var">h</span> <span class="id" type="var">t</span>]. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">simpl</span> <span class="id" type="keyword">in</span> *. <span class="id" type="tactic">split</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">intros</span>. <span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span>; <span class="id" type="tactic">clear</span> <span class="id" type="var">H</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">left</span>. <span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">eqb_stringP</span> <span class="id" type="var">h</span> <span class="id" type="var">x</span>).<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">left</span>. <span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">right</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">filter_In</span>. <span class="id" type="tactic">split</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">IHt</span>. <span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> <span class="id" type="var">false_eqb_string</span>; <span class="id" type="tactic">auto</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;&lt;-&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">intros</span>. <span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span>; <span class="id" type="tactic">clear</span> <span class="id" type="var">H</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">left</span>. <span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">filter_In</span> <span class="id" type="keyword">in</span> <span class="id" type="var">H<sub>0</sub></span>. <span class="id" type="tactic">inversion</span> <span class="id" type="var">H<sub>0</sub></span>. <span class="id" type="var">right</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">IHt</span>. <span class="id" type="tactic">assumption</span>.<br/>
<span class="id" type="keyword">Qed</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Definition</span> <span class="id" type="var">pe_compare</span> (<span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span> : <span class="id" type="var">pe_state</span>) : <span class="id" type="var">list</span> <span class="id" type="var">string</span> :=<br/>
&nbsp;&nbsp;<span class="id" type="var">pe_unique</span> (<span class="id" type="var">filter</span> (<span class="id" type="var">pe_disagree_at</span> <span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">map</span> (@<span class="id" type="var">fst</span> <span class="id" type="var">_</span> <span class="id" type="var">_</span>) <span class="id" type="var">pe_st<sub>1</sub></span> ++ <span class="id" type="var">map</span> (@<span class="id" type="var">fst</span> <span class="id" type="var">_</span> <span class="id" type="var">_</span>) <span class="id" type="var">pe_st<sub>2</sub></span>)).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">pe_compare_correct</span>: <span style='font-size:120%;'>&forall;</span><span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span> <span class="id" type="var">V</span>,<br/>
&nbsp;&nbsp;<span class="id" type="var">pe_lookup</span> <span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">V</span> = <span class="id" type="var">pe_lookup</span> <span class="id" type="var">pe_st<sub>2</sub></span> <span class="id" type="var">V</span> ↔<br/>
&nbsp;&nbsp;¬<span class="id" type="var">In</span> <span class="id" type="var">V</span> (<span class="id" type="var">pe_compare</span> <span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span>).<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span> <span class="id" type="var">V</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">unfold</span> <span class="id" type="var">pe_compare</span>. <span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">pe_unique_correct</span>. <span class="id" type="tactic">rewrite</span> <span class="id" type="var">filter_In</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">split</span>; <span class="id" type="tactic">intros</span> <span class="id" type="var">Heq</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">intro</span>. <span class="id" type="tactic">destruct</span> <span class="id" type="var">H</span>. <span class="id" type="tactic">unfold</span> <span class="id" type="var">pe_disagree_at</span> <span class="id" type="keyword">in</span> <span class="id" type="var">H<sub>0</sub></span>. <span class="id" type="tactic">rewrite</span> <span class="id" type="var">Heq</span> <span class="id" type="keyword">in</span> <span class="id" type="var">H<sub>0</sub></span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">pe_lookup</span> <span class="id" type="var">pe_st<sub>2</sub></span> <span class="id" type="var">V</span>).<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">beq_nat_refl</span> <span class="id" type="keyword">in</span> <span class="id" type="var">H<sub>0</sub></span>. <span class="id" type="tactic">inversion</span> <span class="id" type="var">H<sub>0</sub></span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">H<sub>0</sub></span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;&lt;-&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">assert</span> (<span class="id" type="var">Hagree</span>: <span class="id" type="var">pe_disagree_at</span> <span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span> <span class="id" type="var">V</span> = <span class="id" type="var">false</span>).<br/>
&nbsp;&nbsp;&nbsp;&nbsp;{ <span class="comment">(*&nbsp;对断言的证明&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">remember</span> (<span class="id" type="var">pe_disagree_at</span> <span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span> <span class="id" type="var">V</span>) <span class="id" type="keyword">as</span> <span class="id" type="var">disagree</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> <span class="id" type="var">disagree</span>; [| <span class="id" type="tactic">reflexivity</span>].<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span>  <span class="id" type="var">pe_disagree_domain</span> <span class="id" type="keyword">in</span> <span class="id" type="var">Heqdisagree</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">exfalso</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">Heq</span>. <span class="id" type="tactic">split</span>. <span class="id" type="tactic">assumption</span>. <span class="id" type="tactic">reflexivity</span>. }<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">unfold</span> <span class="id" type="var">pe_disagree_at</span> <span class="id" type="keyword">in</span> <span class="id" type="var">Hagree</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">pe_lookup</span> <span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">V</span>) <span class="id" type="keyword">as</span> [<span class="id" type="var">n<sub>1</sub></span>|];<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">pe_lookup</span> <span class="id" type="var">pe_st<sub>2</sub></span> <span class="id" type="var">V</span>) <span class="id" type="keyword">as</span> [<span class="id" type="var">n<sub>2</sub></span>|];<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">try</span> <span class="id" type="tactic">reflexivity</span>; <span class="id" type="tactic">try</span> <span class="id" type="var">solve_by_invert</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> <span class="id" type="var">negb_false_iff</span> <span class="id" type="keyword">in</span> <span class="id" type="var">Hagree</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">eqb_eq</span> <span class="id" type="keyword">in</span> <span class="id" type="var">Hagree</span>. <span class="id" type="tactic">subst</span>. <span class="id" type="tactic">reflexivity</span>. <span class="id" type="keyword">Qed</span>.<br/>
</div>

<div class="doc">
两个部分状态的交是从其中一个状态中移除所有值不同的变量。我们用上面的
    <span class="inlinecode"><span class="id" type="var">pe_remove</span></span> 来定义函数 <span class="inlinecode"><span class="id" type="var">pe_removes</span></span>，用于一次性地移除一个列表中的变量。

<div class="paragraph"> </div>

    定理 <span class="inlinecode"><span class="id" type="var">pe_compare_removes</span></span> 证明了无论我们从哪个状态中移除变量，最终得到
    的交在 <span class="inlinecode"><span class="id" type="var">pe_lookup</span></span> 的解释下都是相同的。因为 <span class="inlinecode"><span class="id" type="var">pe_update</span></span> 仅依赖 <span class="inlinecode"><span class="id" type="var">pe_lookup</span></span>
    对部分状态的解释，我们选择从哪个状态中移除变量也不会影响到 <span class="inlinecode"><span class="id" type="var">pe_update</span></span>；
    后面的正确性证明中会用到 <span class="inlinecode"><span class="id" type="var">pe_compare_update</span></span> 定理。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Fixpoint</span> <span class="id" type="var">pe_removes</span> (<span class="id" type="var">pe_st</span>:<span class="id" type="var">pe_state</span>) (<span class="id" type="var">ids</span> : <span class="id" type="var">list</span> <span class="id" type="var">string</span>) : <span class="id" type="var">pe_state</span> :=<br/>
&nbsp;&nbsp;<span class="id" type="keyword">match</span> <span class="id" type="var">ids</span> <span class="id" type="keyword">with</span><br/>
&nbsp;&nbsp;| [] ⇒ <span class="id" type="var">pe_st</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">V</span>::<span class="id" type="var">ids</span> ⇒ <span class="id" type="var">pe_remove</span> (<span class="id" type="var">pe_removes</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">ids</span>) <span class="id" type="var">V</span><br/>
&nbsp;&nbsp;<span class="id" type="keyword">end</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">pe_removes_correct</span>: <span style='font-size:120%;'>&forall;</span><span class="id" type="var">pe_st</span> <span class="id" type="var">ids</span> <span class="id" type="var">V</span>,<br/>
&nbsp;&nbsp;<span class="id" type="var">pe_lookup</span> (<span class="id" type="var">pe_removes</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">ids</span>) <span class="id" type="var">V</span> =<br/>
&nbsp;&nbsp;<span class="id" type="keyword">if</span> <span class="id" type="var">inb</span> <span class="id" type="var">eqb_string</span> <span class="id" type="var">V</span> <span class="id" type="var">ids</span> <span class="id" type="keyword">then</span> <span class="id" type="var">None</span> <span class="id" type="keyword">else</span> <span class="id" type="var">pe_lookup</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">V</span>.<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">ids</span> <span class="id" type="var">V</span>. <span class="id" type="tactic">induction</span> <span class="id" type="var">ids</span> <span class="id" type="keyword">as</span> [| <span class="id" type="var">V'</span> <span class="id" type="var">ids</span>]. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">simpl</span>. <span class="id" type="tactic">rewrite</span> <span class="id" type="var">pe_remove_correct</span>. <span class="id" type="tactic">rewrite</span> <span class="id" type="var">IHids</span>.<br/>
&nbsp;&nbsp;<span class="id" type="var">compare</span> <span class="id" type="var">V'</span> <span class="id" type="var">V</span>.<br/>
&nbsp;&nbsp;- <span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">eqb_string_refl</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;- <span class="id" type="tactic">rewrite</span> <span class="id" type="var">false_eqb_string</span>; <span class="id" type="tactic">try</span> <span class="id" type="tactic">congruence</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
<span class="id" type="keyword">Qed</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">pe_compare_removes</span>: <span style='font-size:120%;'>&forall;</span><span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span> <span class="id" type="var">V</span>,<br/>
&nbsp;&nbsp;<span class="id" type="var">pe_lookup</span> (<span class="id" type="var">pe_removes</span> <span class="id" type="var">pe_st<sub>1</sub></span> (<span class="id" type="var">pe_compare</span> <span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span>)) <span class="id" type="var">V</span> =<br/>
&nbsp;&nbsp;<span class="id" type="var">pe_lookup</span> (<span class="id" type="var">pe_removes</span> <span class="id" type="var">pe_st<sub>2</sub></span> (<span class="id" type="var">pe_compare</span> <span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span>)) <span class="id" type="var">V</span>.<br/>
<span class="id" type="keyword">Proof</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span> <span class="id" type="var">V</span>. <span class="id" type="tactic">rewrite</span> !<span class="id" type="var">pe_removes_correct</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">inbP</span> <span class="id" type="var">_</span> <span class="id" type="var">_</span> <span class="id" type="var">eqb_stringP</span> <span class="id" type="var">V</span> (<span class="id" type="var">pe_compare</span> <span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span>)).<br/>
&nbsp;&nbsp;- <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;- <span class="id" type="tactic">apply</span> <span class="id" type="var">pe_compare_correct</span>. <span class="id" type="tactic">auto</span>. <span class="id" type="keyword">Qed</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">pe_compare_update</span>: <span style='font-size:120%;'>&forall;</span><span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span> <span class="id" type="var">st</span>,<br/>
&nbsp;&nbsp;<span class="id" type="var">pe_update</span> <span class="id" type="var">st</span> (<span class="id" type="var">pe_removes</span> <span class="id" type="var">pe_st<sub>1</sub></span> (<span class="id" type="var">pe_compare</span> <span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span>)) =<br/>
&nbsp;&nbsp;<span class="id" type="var">pe_update</span> <span class="id" type="var">st</span> (<span class="id" type="var">pe_removes</span> <span class="id" type="var">pe_st<sub>2</sub></span> (<span class="id" type="var">pe_compare</span> <span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span>)).<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">intros</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">functional_extensionality</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">V</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> !<span class="id" type="var">pe_update_correct</span>. <span class="id" type="tactic">rewrite</span> <span class="id" type="var">pe_compare_removes</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
<span class="id" type="keyword">Qed</span>.<br/>
</div>

<div class="doc">
最后，我们定义 <span class="inlinecode"><span class="id" type="var">assign</span></span> 函数将两个部分状态的差转换为一系列的赋值命令。
    准确地说，<span class="inlinecode"><span class="id" type="var">assign</span></span> <span class="inlinecode"><span class="id" type="var">pe_st</span></span> <span class="inlinecode"><span class="id" type="var">ids</span></span> 对 <span class="inlinecode"><span class="id" type="var">ids</span></span> 中的每个变量生成一个赋值命令。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Fixpoint</span> <span class="id" type="var">assign</span> (<span class="id" type="var">pe_st</span> : <span class="id" type="var">pe_state</span>) (<span class="id" type="var">ids</span> : <span class="id" type="var">list</span> <span class="id" type="var">string</span>) : <span class="id" type="var">com</span> :=<br/>
&nbsp;&nbsp;<span class="id" type="keyword">match</span> <span class="id" type="var">ids</span> <span class="id" type="keyword">with</span><br/>
&nbsp;&nbsp;| [] ⇒ <span class="id" type="var">SKIP</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">V</span>::<span class="id" type="var">ids</span> ⇒ <span class="id" type="keyword">match</span> <span class="id" type="var">pe_lookup</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">V</span> <span class="id" type="keyword">with</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| <span class="id" type="var">Some</span> <span class="id" type="var">n</span> ⇒ (<span class="id" type="var">assign</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">ids</span>;; <span class="id" type="var">V</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">ANum</span> <span class="id" type="var">n</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| <span class="id" type="var">None</span> ⇒ <span class="id" type="var">assign</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">ids</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">end</span><br/>
&nbsp;&nbsp;<span class="id" type="keyword">end</span>.<br/>
</div>

<div class="doc">
由 <span class="inlinecode"><span class="id" type="var">assign</span></span> 生成的命令总是会停机，因为他们仅仅是赋值命令而已。下面的（全）函数
    <span class="inlinecode"><span class="id" type="var">assigned</span></span> 计算了命令在动态状态上的作用。定理 <span class="inlinecode"><span class="id" type="var">assign_removes</span></span> 进一步确认了
    生成的赋值语句抵消了部分状态中所移除的变量。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Definition</span> <span class="id" type="var">assigned</span> (<span class="id" type="var">pe_st</span>:<span class="id" type="var">pe_state</span>) (<span class="id" type="var">ids</span> : <span class="id" type="var">list</span> <span class="id" type="var">string</span>) (<span class="id" type="var">st</span>:<span class="id" type="var">state</span>) : <span class="id" type="var">state</span> :=<br/>
&nbsp;&nbsp;<span class="id" type="keyword">fun</span> <span class="id" type="var">V</span> ⇒ <span class="id" type="keyword">if</span> <span class="id" type="var">inb</span> <span class="id" type="var">eqb_string</span> <span class="id" type="var">V</span> <span class="id" type="var">ids</span> <span class="id" type="keyword">then</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">match</span> <span class="id" type="var">pe_lookup</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">V</span> <span class="id" type="keyword">with</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| <span class="id" type="var">Some</span> <span class="id" type="var">n</span> ⇒ <span class="id" type="var">n</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| <span class="id" type="var">None</span> ⇒ <span class="id" type="var">st</span> <span class="id" type="var">V</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">end</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">else</span> <span class="id" type="var">st</span> <span class="id" type="var">V</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">assign_removes</span>: <span style='font-size:120%;'>&forall;</span><span class="id" type="var">pe_st</span> <span class="id" type="var">ids</span> <span class="id" type="var">st</span>,<br/>
&nbsp;&nbsp;<span class="id" type="var">pe_update</span> <span class="id" type="var">st</span> <span class="id" type="var">pe_st</span> =<br/>
&nbsp;&nbsp;<span class="id" type="var">pe_update</span> (<span class="id" type="var">assigned</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">ids</span> <span class="id" type="var">st</span>) (<span class="id" type="var">pe_removes</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">ids</span>).<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">ids</span> <span class="id" type="var">st</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">functional_extensionality</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">V</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> !<span class="id" type="var">pe_update_correct</span>. <span class="id" type="tactic">rewrite</span> <span class="id" type="var">pe_removes_correct</span>. <span class="id" type="tactic">unfold</span> <span class="id" type="var">assigned</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">inbP</span> <span class="id" type="var">_</span> <span class="id" type="var">_</span> <span class="id" type="var">eqb_stringP</span> <span class="id" type="var">V</span> <span class="id" type="var">ids</span>); <span class="id" type="tactic">destruct</span> (<span class="id" type="var">pe_lookup</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">V</span>); <span class="id" type="tactic">reflexivity</span>.<br/>
<span class="id" type="keyword">Qed</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Lemma</span> <span class="id" type="var">ceval_extensionality</span>: <span style='font-size:120%;'>&forall;</span><span class="id" type="var">c</span> <span class="id" type="var">st</span> <span class="id" type="var">st<sub>1</sub></span> <span class="id" type="var">st<sub>2</sub></span>,<br/>
&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">c</span> ]⇒ <span class="id" type="var">st<sub>1</sub></span> → (<span style='font-size:120%;'>&forall;</span><span class="id" type="var">V</span>, <span class="id" type="var">st<sub>1</sub></span> <span class="id" type="var">V</span> = <span class="id" type="var">st<sub>2</sub></span> <span class="id" type="var">V</span>) → <span class="id" type="var">st</span> =[ <span class="id" type="var">c</span> ]⇒ <span class="id" type="var">st<sub>2</sub></span>.<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">c</span> <span class="id" type="var">st</span> <span class="id" type="var">st<sub>1</sub></span> <span class="id" type="var">st<sub>2</sub></span> <span class="id" type="var">H</span> <span class="id" type="var">Heq</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">functional_extensionality</span> <span class="id" type="keyword">in</span> <span class="id" type="var">Heq</span>. <span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">Heq</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">H</span>. <span class="id" type="keyword">Qed</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">eval_assign</span>: <span style='font-size:120%;'>&forall;</span><span class="id" type="var">pe_st</span> <span class="id" type="var">ids</span> <span class="id" type="var">st</span>,<br/>
&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">assign</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">ids</span> ]⇒ <span class="id" type="var">assigned</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">ids</span> <span class="id" type="var">st</span>.<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">ids</span> <span class="id" type="var">st</span>. <span class="id" type="tactic">induction</span> <span class="id" type="var">ids</span> <span class="id" type="keyword">as</span> [| <span class="id" type="var">V</span> <span class="id" type="var">ids</span>]; <span class="id" type="tactic">simpl</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;<span class="inlinecode"></span>&nbsp;*)</span> <span class="id" type="tactic">eapply</span> <span class="id" type="var">ceval_extensionality</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">E_Skip</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;V::ids&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">remember</span> (<span class="id" type="var">pe_lookup</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">V</span>) <span class="id" type="keyword">as</span> <span class="id" type="var">lookup</span>. <span class="id" type="tactic">destruct</span> <span class="id" type="var">lookup</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;Some&nbsp;*)</span> <span class="id" type="tactic">eapply</span> <span class="id" type="var">E_Seq</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">IHids</span>. <span class="id" type="tactic">unfold</span> <span class="id" type="var">assigned</span>. <span class="id" type="tactic">simpl</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">ceval_extensionality</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">E_Ass</span>. <span class="id" type="tactic">simpl</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">V<sub>0</sub></span>. <span class="id" type="tactic">unfold</span> <span class="id" type="var">t_update</span>. <span class="id" type="var">compare</span> <span class="id" type="var">V</span> <span class="id" type="var">V<sub>0</sub></span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* <span class="comment">(*&nbsp;相等&nbsp;*)</span> <span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">Heqlookup</span>. <span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">eqb_string_refl</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* <span class="comment">(*&nbsp;不相等&nbsp;*)</span> <span class="id" type="tactic">rewrite</span> <span class="id" type="var">false_eqb_string</span>; <span class="id" type="tactic">simpl</span>; <span class="id" type="tactic">congruence</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;None&nbsp;*)</span> <span class="id" type="tactic">eapply</span> <span class="id" type="var">ceval_extensionality</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">IHids</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">unfold</span> <span class="id" type="var">assigned</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">V<sub>0</sub></span>. <span class="id" type="tactic">simpl</span>. <span class="id" type="var">compare</span> <span class="id" type="var">V</span> <span class="id" type="var">V<sub>0</sub></span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* <span class="comment">(*&nbsp;相等&nbsp;*)</span> <span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">Heqlookup</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">eqb_string_refl</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">inbP</span> <span class="id" type="var">_</span> <span class="id" type="var">_</span> <span class="id" type="var">eqb_stringP</span> <span class="id" type="var">V</span> <span class="id" type="var">ids</span>); <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* <span class="comment">(*&nbsp;不相等&nbsp;*)</span> <span class="id" type="tactic">rewrite</span> <span class="id" type="var">false_eqb_string</span>; <span class="id" type="tactic">simpl</span>; <span class="id" type="tactic">congruence</span>.<br/>
<span class="id" type="keyword">Qed</span>.<br/>
</div>

<div class="doc">
<a name="lab583"></a><h2 class="section">部分求值关系</h2>

<div class="paragraph"> </div>

 终于，我们可以将无循环命令的部分求值器定义为一个归纳关系了！
    <span class="inlinecode"><span class="id" type="var">PE_AssDynamic</span></span> 和 <span class="inlinecode"><span class="id" type="var">PE_If</span></span> 中的不等式仅仅是为了使部分求值器
    保持确定性；他们并不是正确性所需要的。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Reserved Notation</span> "c<sub>1</sub> '/' st '\\' c<sub>1</sub>' '/' st'"<br/>
&nbsp;&nbsp;(<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 40, <span class="id" type="var">st</span> <span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 39, <span class="id" type="var">c<sub>1</sub>'</span> <span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 39).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Inductive</span> <span class="id" type="var">pe_com</span> : <span class="id" type="var">com</span> → <span class="id" type="var">pe_state</span> → <span class="id" type="var">com</span> → <span class="id" type="var">pe_state</span> → <span class="id" type="keyword">Prop</span> :=<br/>
&nbsp;&nbsp;| <span class="id" type="var">PE_Skip</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">pe_st</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">SKIP</span> / <span class="id" type="var">pe_st</span> \\ <span class="id" type="var">SKIP</span> / <span class="id" type="var">pe_st</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">PE_AssStatic</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">pe_st</span> <span class="id" type="var">a<sub>1</sub></span> <span class="id" type="var">n<sub>1</sub></span> <span class="id" type="var">l</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">pe_aexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">a<sub>1</sub></span> = <span class="id" type="var">ANum</span> <span class="id" type="var">n<sub>1</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">l</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">a<sub>1</sub></span>) / <span class="id" type="var">pe_st</span> \\ <span class="id" type="var">SKIP</span> / <span class="id" type="var">pe_add</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">l</span> <span class="id" type="var">n<sub>1</sub></span><br/>
&nbsp;&nbsp;| <span class="id" type="var">PE_AssDynamic</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">pe_st</span> <span class="id" type="var">a<sub>1</sub></span> <span class="id" type="var">a<sub>1</sub>'</span> <span class="id" type="var">l</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">pe_aexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">a<sub>1</sub></span> = <span class="id" type="var">a<sub>1</sub>'</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span style='font-size:120%;'>&forall;</span><span class="id" type="var">n</span>, <span class="id" type="var">a<sub>1</sub>'</span> ≠ <span class="id" type="var">ANum</span> <span class="id" type="var">n</span>) →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">l</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">a<sub>1</sub></span>) / <span class="id" type="var">pe_st</span> \\ (<span class="id" type="var">l</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">a<sub>1</sub>'</span>) / <span class="id" type="var">pe_remove</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">l</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">PE_Seq</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">pe_st</span> <span class="id" type="var">pe_st'</span> <span class="id" type="var">pe_st''</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">c<sub>1</sub>'</span> <span class="id" type="var">c<sub>2</sub>'</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">c<sub>1</sub></span> / <span class="id" type="var">pe_st</span>  \\ <span class="id" type="var">c<sub>1</sub>'</span> / <span class="id" type="var">pe_st'</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">c<sub>2</sub></span> / <span class="id" type="var">pe_st'</span> \\ <span class="id" type="var">c<sub>2</sub>'</span> / <span class="id" type="var">pe_st''</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">c<sub>1</sub></span> ;; <span class="id" type="var">c<sub>2</sub></span>) / <span class="id" type="var">pe_st</span> \\ (<span class="id" type="var">c<sub>1</sub>'</span> ;; <span class="id" type="var">c<sub>2</sub>'</span>) / <span class="id" type="var">pe_st''</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">PE_IfTrue</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">pe_st</span> <span class="id" type="var">pe_st'</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">c<sub>1</sub>'</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">pe_bexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">b<sub>1</sub></span> = <span class="id" type="var">BTrue</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">c<sub>1</sub></span> / <span class="id" type="var">pe_st</span> \\ <span class="id" type="var">c<sub>1</sub>'</span> / <span class="id" type="var">pe_st'</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">TEST</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">THEN</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">ELSE</span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">FI</span>) / <span class="id" type="var">pe_st</span> \\ <span class="id" type="var">c<sub>1</sub>'</span> / <span class="id" type="var">pe_st'</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">PE_IfFalse</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">pe_st</span> <span class="id" type="var">pe_st'</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">c<sub>2</sub>'</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">pe_bexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">b<sub>1</sub></span> = <span class="id" type="var">BFalse</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">c<sub>2</sub></span> / <span class="id" type="var">pe_st</span> \\ <span class="id" type="var">c<sub>2</sub>'</span> / <span class="id" type="var">pe_st'</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">TEST</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">THEN</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">ELSE</span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">FI</span>) / <span class="id" type="var">pe_st</span> \\ <span class="id" type="var">c<sub>2</sub>'</span> / <span class="id" type="var">pe_st'</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">PE_If</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">pe_st</span> <span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">c<sub>1</sub>'</span> <span class="id" type="var">c<sub>2</sub>'</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">pe_bexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">b<sub>1</sub></span> ≠ <span class="id" type="var">BTrue</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">pe_bexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">b<sub>1</sub></span> ≠ <span class="id" type="var">BFalse</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">c<sub>1</sub></span> / <span class="id" type="var">pe_st</span> \\ <span class="id" type="var">c<sub>1</sub>'</span> / <span class="id" type="var">pe_st<sub>1</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">c<sub>2</sub></span> / <span class="id" type="var">pe_st</span> \\ <span class="id" type="var">c<sub>2</sub>'</span> / <span class="id" type="var">pe_st<sub>2</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">TEST</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">THEN</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">ELSE</span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">FI</span>) / <span class="id" type="var">pe_st</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\\ (<span class="id" type="var">TEST</span> <span class="id" type="var">pe_bexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">b<sub>1</sub></span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">THEN</span> <span class="id" type="var">c<sub>1</sub>'</span> ;; <span class="id" type="var">assign</span> <span class="id" type="var">pe_st<sub>1</sub></span> (<span class="id" type="var">pe_compare</span> <span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">ELSE</span> <span class="id" type="var">c<sub>2</sub>'</span> ;; <span class="id" type="var">assign</span> <span class="id" type="var">pe_st<sub>2</sub></span> (<span class="id" type="var">pe_compare</span> <span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span>) <span class="id" type="var">FI</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/ <span class="id" type="var">pe_removes</span> <span class="id" type="var">pe_st<sub>1</sub></span> (<span class="id" type="var">pe_compare</span> <span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span>)<br/>
<br/>
&nbsp;&nbsp;<span class="id" type="keyword">where</span> "c<sub>1</sub> '/' st '\\' c<sub>1</sub>' '/' st'" := (<span class="id" type="var">pe_com</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">st</span> <span class="id" type="var">c<sub>1</sub>'</span> <span class="id" type="var">st'</span>).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Hint</span> <span class="id" type="var">Constructors</span> <span class="id" type="var">pe_com</span>.<br/>
<span class="id" type="keyword">Hint</span> <span class="id" type="var">Constructors</span> <span class="id" type="var">ceval</span>.<br/>
</div>

<div class="doc">
<a name="lab584"></a><h2 class="section">例子</h2>

<div class="paragraph"> </div>

 下面给出一些使用部分求值器的例子。为了使 <span class="inlinecode"><span class="id" type="var">pe_com</span></span> 关系可以自动化地完成
    部分求值，我们会需要在 Coq 中定义一些自动化的策略。这不会十分困难，
    但这里并不是必须的。 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Example</span> <span class="id" type="var">pe_example1</span>:<br/>
&nbsp;&nbsp;(<span class="id" type="var">X</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> 3 ;; <span class="id" type="var">Y</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">Z</span> * (<span class="id" type="var">X</span> + <span class="id" type="var">X</span>))%<span class="id" type="var">imp</span><br/>
&nbsp;&nbsp;/ [] \\ (<span class="id" type="var">SKIP</span>;; <span class="id" type="var">Y</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">Z</span> * 6)%<span class="id" type="var">imp</span> / [(<span class="id" type="var">X</span>,3)].<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">eapply</span> <span class="id" type="var">PE_Seq</span>. <span class="id" type="tactic">eapply</span> <span class="id" type="var">PE_AssStatic</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">PE_AssDynamic</span>. <span class="id" type="tactic">reflexivity</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">n</span> <span class="id" type="var">H</span>. <span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span>. <span class="id" type="keyword">Qed</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">pe_example2</span>:<br/>
&nbsp;&nbsp;(<span class="id" type="var">X</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> 3 ;; <span class="id" type="var">TEST</span> <span class="id" type="var">X</span> ≤ 4 <span class="id" type="var">THEN</span> <span class="id" type="var">X</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> 4 <span class="id" type="var">ELSE</span> <span class="id" type="var">SKIP</span> <span class="id" type="var">FI</span>)%<span class="id" type="var">imp</span><br/>
&nbsp;&nbsp;/ [] \\ (<span class="id" type="var">SKIP</span>;; <span class="id" type="var">SKIP</span>)%<span class="id" type="var">imp</span> / [(<span class="id" type="var">X</span>,4)].<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">eapply</span> <span class="id" type="var">PE_Seq</span>. <span class="id" type="tactic">eapply</span> <span class="id" type="var">PE_AssStatic</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">PE_IfTrue</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">PE_AssStatic</span>. <span class="id" type="tactic">reflexivity</span>. <span class="id" type="keyword">Qed</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">pe_example3</span>:<br/>
&nbsp;&nbsp;(<span class="id" type="var">X</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> 3;;<br/>
&nbsp;&nbsp;&nbsp;<span class="id" type="var">TEST</span> <span class="id" type="var">Y</span> ≤ 4 <span class="id" type="var">THEN</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Y</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> 4;;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">TEST</span> <span class="id" type="var">X</span> = <span class="id" type="var">Y</span> <span class="id" type="var">THEN</span> <span class="id" type="var">Y</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> 999 <span class="id" type="var">ELSE</span> <span class="id" type="var">SKIP</span> <span class="id" type="var">FI</span><br/>
&nbsp;&nbsp;&nbsp;<span class="id" type="var">ELSE</span> <span class="id" type="var">SKIP</span> <span class="id" type="var">FI</span>)%<span class="id" type="var">imp</span> / []<br/>
&nbsp;&nbsp;\\ (<span class="id" type="var">SKIP</span>;;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">TEST</span> <span class="id" type="var">Y</span> ≤ 4 <span class="id" type="var">THEN</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">SKIP</span>;; <span class="id" type="var">SKIP</span>);; (<span class="id" type="var">SKIP</span>;; <span class="id" type="var">Y</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> 4)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">ELSE</span> <span class="id" type="var">SKIP</span>;; <span class="id" type="var">SKIP</span> <span class="id" type="var">FI</span>)%<span class="id" type="var">imp</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/ [(<span class="id" type="var">X</span>,3)].<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="var">erewrite</span> <span class="id" type="var">f_equal2</span> <span class="id" type="keyword">with</span> (<span class="id" type="var">f</span> := <span class="id" type="keyword">fun</span> <span class="id" type="var">c</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">_</span> / <span class="id" type="var">_</span> \\ <span class="id" type="var">c</span> / <span class="id" type="var">st</span>).<br/>
&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">PE_Seq</span>. <span class="id" type="tactic">eapply</span> <span class="id" type="var">PE_AssStatic</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">PE_If</span>; <span class="id" type="tactic">intuition</span> <span class="id" type="tactic">eauto</span>; <span class="id" type="tactic">try</span> <span class="id" type="var">solve_by_invert</span>.<br/>
&nbsp;&nbsp;<span class="id" type="var">econstructor</span>. <span class="id" type="tactic">eapply</span> <span class="id" type="var">PE_AssStatic</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">PE_IfFalse</span>. <span class="id" type="tactic">reflexivity</span>. <span class="id" type="var">econstructor</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">reflexivity</span>. <span class="id" type="tactic">reflexivity</span>. <span class="id" type="keyword">Qed</span>.<br/>
</div>

<div class="doc">
<a name="lab585"></a><h2 class="section">部分求值的正确性</h2>

<div class="paragraph"> </div>

 最后，让我们来证明这个部分求值器是正确的！ 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Reserved Notation</span> "c' '/' pe_st' '/' st '\\' st''"<br/>
&nbsp;&nbsp;(<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 40, <span class="id" type="var">pe_st'</span> <span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 39, <span class="id" type="var">st</span> <span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 39).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Inductive</span> <span class="id" type="var">pe_ceval</span><br/>
&nbsp;&nbsp;(<span class="id" type="var">c'</span>:<span class="id" type="var">com</span>) (<span class="id" type="var">pe_st'</span>:<span class="id" type="var">pe_state</span>) (<span class="id" type="var">st</span>:<span class="id" type="var">state</span>) (<span class="id" type="var">st''</span>:<span class="id" type="var">state</span>) : <span class="id" type="keyword">Prop</span> :=<br/>
&nbsp;&nbsp;| <span class="id" type="var">pe_ceval_intro</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st'</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">c'</span> ]⇒ <span class="id" type="var">st'</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">pe_update</span> <span class="id" type="var">st'</span> <span class="id" type="var">pe_st'</span> = <span class="id" type="var">st''</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">c'</span> / <span class="id" type="var">pe_st'</span> / <span class="id" type="var">st</span> \\ <span class="id" type="var">st''</span><br/>
&nbsp;&nbsp;<span class="id" type="keyword">where</span> "c' '/' pe_st' '/' st '\\' st''" := (<span class="id" type="var">pe_ceval</span> <span class="id" type="var">c'</span> <span class="id" type="var">pe_st'</span> <span class="id" type="var">st</span> <span class="id" type="var">st''</span>).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Hint</span> <span class="id" type="var">Constructors</span> <span class="id" type="var">pe_ceval</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">pe_com_complete</span>:<br/>
&nbsp;&nbsp;<span style='font-size:120%;'>&forall;</span><span class="id" type="var">c</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">pe_st'</span> <span class="id" type="var">c'</span>, <span class="id" type="var">c</span> / <span class="id" type="var">pe_st</span> \\ <span class="id" type="var">c'</span> / <span class="id" type="var">pe_st'</span> →<br/>
&nbsp;&nbsp;<span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">st''</span>,<br/>
&nbsp;&nbsp;(<span class="id" type="var">pe_update</span> <span class="id" type="var">st</span> <span class="id" type="var">pe_st</span> =[ <span class="id" type="var">c</span> ]⇒ <span class="id" type="var">st''</span>) →<br/>
&nbsp;&nbsp;(<span class="id" type="var">c'</span> / <span class="id" type="var">pe_st'</span> / <span class="id" type="var">st</span> \\ <span class="id" type="var">st''</span>).<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">c</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">pe_st'</span> <span class="id" type="var">c'</span> <span class="id" type="var">Hpe</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">induction</span> <span class="id" type="var">Hpe</span>; <span class="id" type="tactic">intros</span> <span class="id" type="var">st</span> <span class="id" type="var">st''</span> <span class="id" type="var">Heval</span>;<br/>
&nbsp;&nbsp;<span class="id" type="tactic">try</span> (<span class="id" type="tactic">inversion</span> <span class="id" type="var">Heval</span>; <span class="id" type="tactic">subst</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">try</span> (<span class="id" type="tactic">rewrite</span> → <span class="id" type="var">pe_bexp_correct</span>, → <span class="id" type="var">H</span> <span class="id" type="keyword">in</span> *; <span class="id" type="var">solve_by_invert</span>);<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[]);<br/>
&nbsp;&nbsp;<span class="id" type="tactic">eauto</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;PE_AssStatic&nbsp;*)</span> <span class="id" type="var">econstructor</span>. <span class="id" type="var">econstructor</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> → <span class="id" type="var">pe_aexp_correct</span>. <span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">pe_update_update_add</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> → <span class="id" type="var">H</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;PE_AssDynamic&nbsp;*)</span> <span class="id" type="var">econstructor</span>. <span class="id" type="var">econstructor</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> → <span class="id" type="var">pe_aexp_correct</span>. <span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">pe_update_update_remove</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;PE_Seq&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">edestruct</span> <span class="id" type="var">IHHpe1</span>. <span class="id" type="var">eassumption</span>. <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">edestruct</span> <span class="id" type="var">IHHpe2</span>. <span class="id" type="var">eassumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eauto</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;PE_If&nbsp;*)</span> <span class="id" type="tactic">inversion</span> <span class="id" type="var">Heval</span>; <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;E'IfTrue&nbsp;*)</span> <span class="id" type="var">edestruct</span> <span class="id" type="var">IHHpe1</span>. <span class="id" type="var">eassumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">econstructor</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">E_IfTrue</span>. <span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">pe_bexp_correct</span>. <span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">E_Seq</span>. <span class="id" type="var">eassumption</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">eval_assign</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">assign_removes</span>. <span class="id" type="var">eassumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;E_IfFalse&nbsp;*)</span> <span class="id" type="var">edestruct</span> <span class="id" type="var">IHHpe2</span>. <span class="id" type="var">eassumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">econstructor</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">E_IfFalse</span>. <span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">pe_bexp_correct</span>. <span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">E_Seq</span>. <span class="id" type="var">eassumption</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">eval_assign</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> → <span class="id" type="var">pe_compare_update</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">assign_removes</span>. <span class="id" type="var">eassumption</span>.<br/>
<span class="id" type="keyword">Qed</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">pe_com_sound</span>:<br/>
&nbsp;&nbsp;<span style='font-size:120%;'>&forall;</span><span class="id" type="var">c</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">pe_st'</span> <span class="id" type="var">c'</span>, <span class="id" type="var">c</span> / <span class="id" type="var">pe_st</span> \\ <span class="id" type="var">c'</span> / <span class="id" type="var">pe_st'</span> →<br/>
&nbsp;&nbsp;<span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">st''</span>,<br/>
&nbsp;&nbsp;(<span class="id" type="var">c'</span> / <span class="id" type="var">pe_st'</span> / <span class="id" type="var">st</span> \\ <span class="id" type="var">st''</span>) →<br/>
&nbsp;&nbsp;(<span class="id" type="var">pe_update</span> <span class="id" type="var">st</span> <span class="id" type="var">pe_st</span> =[ <span class="id" type="var">c</span> ]⇒ <span class="id" type="var">st''</span>).<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">c</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">pe_st'</span> <span class="id" type="var">c'</span> <span class="id" type="var">Hpe</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">induction</span> <span class="id" type="var">Hpe</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">st</span> <span class="id" type="var">st''</span> [<span class="id" type="var">st'</span> <span class="id" type="var">Heval</span> <span class="id" type="var">Heq</span>];<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">try</span> (<span class="id" type="tactic">inversion</span> <span class="id" type="var">Heval</span>; []; <span class="id" type="tactic">subst</span>); <span class="id" type="tactic">auto</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;PE_AssStatic&nbsp;*)</span> <span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">pe_update_update_add</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">E_Ass</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> → <span class="id" type="var">pe_aexp_correct</span>. <span class="id" type="tactic">rewrite</span> → <span class="id" type="var">H</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;PE_AssDynamic&nbsp;*)</span> <span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">pe_update_update_remove</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">E_Ass</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">pe_aexp_correct</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;PE_Seq&nbsp;*)</span> <span class="id" type="tactic">eapply</span> <span class="id" type="var">E_Seq</span>; <span class="id" type="tactic">eauto</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;PE_IfTrue&nbsp;*)</span> <span class="id" type="tactic">apply</span> <span class="id" type="var">E_IfTrue</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> → <span class="id" type="var">pe_bexp_correct</span>. <span class="id" type="tactic">rewrite</span> → <span class="id" type="var">H</span>. <span class="id" type="tactic">reflexivity</span>. <span class="id" type="tactic">eauto</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;PE_IfFalse&nbsp;*)</span> <span class="id" type="tactic">apply</span> <span class="id" type="var">E_IfFalse</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> → <span class="id" type="var">pe_bexp_correct</span>. <span class="id" type="tactic">rewrite</span> → <span class="id" type="var">H</span>. <span class="id" type="tactic">reflexivity</span>. <span class="id" type="tactic">eauto</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;PE_If&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">Heval</span>; <span class="id" type="tactic">subst</span>; <span class="id" type="tactic">inversion</span> <span class="id" type="var">H<sub>7</sub></span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="tactic">eapply</span> <span class="id" type="var">ceval_deterministic</span> <span class="id" type="keyword">in</span> <span class="id" type="var">H<sub>8</sub></span>; [| <span class="id" type="tactic">apply</span> <span class="id" type="var">eval_assign</span>]); <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;E_IfTrue&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">E_IfTrue</span>. <span class="id" type="tactic">rewrite</span> → <span class="id" type="var">pe_bexp_correct</span>. <span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">assign_removes</span>. <span class="id" type="tactic">eauto</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;E_IfFalse&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> → <span class="id" type="var">pe_compare_update</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">E_IfFalse</span>. <span class="id" type="tactic">rewrite</span> → <span class="id" type="var">pe_bexp_correct</span>. <span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">assign_removes</span>. <span class="id" type="tactic">eauto</span>.<br/>
<span class="id" type="keyword">Qed</span>.<br/>
</div>

<div class="doc">
最终的主定理。感谢 David Menendez 所贡献的这个公式！ 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Corollary</span> <span class="id" type="var">pe_com_correct</span>:<br/>
&nbsp;&nbsp;<span style='font-size:120%;'>&forall;</span><span class="id" type="var">c</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">pe_st'</span> <span class="id" type="var">c'</span>, <span class="id" type="var">c</span> / <span class="id" type="var">pe_st</span> \\ <span class="id" type="var">c'</span> / <span class="id" type="var">pe_st'</span> →<br/>
&nbsp;&nbsp;<span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">st''</span>,<br/>
&nbsp;&nbsp;(<span class="id" type="var">pe_update</span> <span class="id" type="var">st</span> <span class="id" type="var">pe_st</span> =[ <span class="id" type="var">c</span> ]⇒ <span class="id" type="var">st''</span>) ↔<br/>
&nbsp;&nbsp;(<span class="id" type="var">c'</span> / <span class="id" type="var">pe_st'</span> / <span class="id" type="var">st</span> \\ <span class="id" type="var">st''</span>).<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">c</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">pe_st'</span> <span class="id" type="var">c'</span> <span class="id" type="var">H</span> <span class="id" type="var">st</span> <span class="id" type="var">st''</span>. <span class="id" type="tactic">split</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;*)</span> <span class="id" type="tactic">apply</span> <span class="id" type="var">pe_com_complete</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">H</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;&lt;-&nbsp;*)</span> <span class="id" type="tactic">apply</span> <span class="id" type="var">pe_com_sound</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">H</span>.<br/>
<span class="id" type="keyword">Qed</span>.<br/>
</div>

<div class="doc">
<a name="lab586"></a><h1 class="section">循环的部分求值</h1>

<div class="paragraph"> </div>

 初看上去，将部分求值关系 <span class="inlinecode"><span class="id" type="var">pe_com</span></span> 扩展到循环是简单直接的。确实，很多循环程序
    是容易处理的。比如说，考虑下面重复计算平方的循环：

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">WHILE</span>&nbsp;1&nbsp;≤&nbsp;<span class="id" type="var">X</span>&nbsp;<span class="id" type="var">DO</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Y</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;<span class="id" type="var">Y</span>&nbsp;*&nbsp;<span class="id" type="var">Y</span>;;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;<span class="id" type="var">X</span>&nbsp;-&nbsp;1<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">END</span>
<div class="paragraph"> </div>

</div>
    如果我们不知道 <span class="inlinecode"><span class="id" type="var">X</span></span> 或 <span class="inlinecode"><span class="id" type="var">Y</span></span> 的静态值，那么整个循环是动态的，其剩余程序与源程序相同。
    如果我们知道 <span class="inlinecode"><span class="id" type="var">X</span></span> 但不知道 <span class="inlinecode"><span class="id" type="var">Y</span></span>，那么循环可以被展开，最后的剩余程序可能是

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Y</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;<span class="id" type="var">Y</span>&nbsp;*&nbsp;<span class="id" type="var">Y</span>;;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Y</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;<span class="id" type="var">Y</span>&nbsp;*&nbsp;<span class="id" type="var">Y</span>;;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Y</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;<span class="id" type="var">Y</span>&nbsp;*&nbsp;<span class="id" type="var">Y</span>
<div class="paragraph"> </div>

</div>
    当 <span class="inlinecode"><span class="id" type="var">X</span></span> 初始为 <span class="inlinecode">3</span> 时（最终变为 <span class="inlinecode">0</span>）。一般来说，如果循环体的最终部分状态和初始状态
    相同，或者其条件是静态的，那么对循环的部分求值很容易。

<div class="paragraph"> </div>

    但是其他的循环程序则很难在 Imp 中表达出我们期待的剩余程序。举个例子，下面的程序检查
    <span class="inlinecode"><span class="id" type="var">Y</span></span> 是奇数还是偶数：

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;0;;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">WHILE</span>&nbsp;1&nbsp;≤&nbsp;<span class="id" type="var">Y</span>&nbsp;<span class="id" type="var">DO</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Y</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;<span class="id" type="var">Y</span>&nbsp;-&nbsp;1&nbsp;;;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;1&nbsp;-&nbsp;<span class="id" type="var">X</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">END</span>
<div class="paragraph"> </div>

</div>
    <span class="inlinecode"><span class="id" type="var">X</span></span> 的值在循环过程中交替地为 <span class="inlinecode">0</span> 或 <span class="inlinecode">1</span>。理想情况，我们想要展开循环两次，
    而非不加限制地，并得到类似如下程序

<div class="paragraph"> </div>

<div class="code code-tight">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">WHILE</span>&nbsp;1&nbsp;≤&nbsp;<span class="id" type="var">Y</span>&nbsp;<span class="id" type="var">DO</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Y</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;<span class="id" type="var">Y</span>&nbsp;-&nbsp;1;;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">IF</span>&nbsp;1&nbsp;≤&nbsp;<span class="id" type="var">Y</span>&nbsp;<span class="id" type="var">THEN</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Y</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;<span class="id" type="var">Y</span>&nbsp;-&nbsp;1<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">ELSE</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;1;;&nbsp;<span class="id" type="var">EXIT</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">FI</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">END</span>;;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">X</span>&nbsp;<span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span>&nbsp;0
<div class="paragraph"> </div>

</div>
    不幸地是，Imp 中并没有 <span class="inlinecode"><span class="id" type="var">EXIT</span></span> 命令。在不对语言扩展控制结构的情况，我们能采取的
    最好方法是是重复循环条件或添加标记变量。不论哪种都不是非常有吸引力。

<div class="paragraph"> </div>

    作为一个题外话，下面是一个对 Imp 命令进行部分求值的尝试。我们对 <span class="inlinecode"><span class="id" type="var">pe_com</span></span>
    关系添加一个新的命令参数 <span class="inlinecode"><span class="id" type="var">c''</span></span>，用于记录循环的累积。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Module</span> <span class="id" type="var">Loop</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Reserved Notation</span> "c<sub>1</sub> '/' st '\\' c<sub>1</sub>' '/' st' '/' c''"<br/>
&nbsp;&nbsp;(<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 40, <span class="id" type="var">st</span> <span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 39, <span class="id" type="var">c<sub>1</sub>'</span> <span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 39, <span class="id" type="var">st'</span> <span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 39).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Inductive</span> <span class="id" type="var">pe_com</span> : <span class="id" type="var">com</span> → <span class="id" type="var">pe_state</span> → <span class="id" type="var">com</span> → <span class="id" type="var">pe_state</span> → <span class="id" type="var">com</span> → <span class="id" type="keyword">Prop</span> :=<br/>
&nbsp;&nbsp;| <span class="id" type="var">PE_Skip</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">pe_st</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">SKIP</span> / <span class="id" type="var">pe_st</span> \\ <span class="id" type="var">SKIP</span> / <span class="id" type="var">pe_st</span> / <span class="id" type="var">SKIP</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">PE_AssStatic</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">pe_st</span> <span class="id" type="var">a<sub>1</sub></span> <span class="id" type="var">n<sub>1</sub></span> <span class="id" type="var">l</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">pe_aexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">a<sub>1</sub></span> = <span class="id" type="var">ANum</span> <span class="id" type="var">n<sub>1</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">l</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">a<sub>1</sub></span>) / <span class="id" type="var">pe_st</span> \\ <span class="id" type="var">SKIP</span> / <span class="id" type="var">pe_add</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">l</span> <span class="id" type="var">n<sub>1</sub></span> / <span class="id" type="var">SKIP</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">PE_AssDynamic</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">pe_st</span> <span class="id" type="var">a<sub>1</sub></span> <span class="id" type="var">a<sub>1</sub>'</span> <span class="id" type="var">l</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">pe_aexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">a<sub>1</sub></span> = <span class="id" type="var">a<sub>1</sub>'</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span style='font-size:120%;'>&forall;</span><span class="id" type="var">n</span>, <span class="id" type="var">a<sub>1</sub>'</span> ≠ <span class="id" type="var">ANum</span> <span class="id" type="var">n</span>) →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">l</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">a<sub>1</sub></span>) / <span class="id" type="var">pe_st</span> \\ (<span class="id" type="var">l</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">a<sub>1</sub>'</span>) / <span class="id" type="var">pe_remove</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">l</span> / <span class="id" type="var">SKIP</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">PE_Seq</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">pe_st</span> <span class="id" type="var">pe_st'</span> <span class="id" type="var">pe_st''</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">c<sub>1</sub>'</span> <span class="id" type="var">c<sub>2</sub>'</span> <span class="id" type="var">c''</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">c<sub>1</sub></span> / <span class="id" type="var">pe_st</span>  \\ <span class="id" type="var">c<sub>1</sub>'</span> / <span class="id" type="var">pe_st'</span> / <span class="id" type="var">SKIP</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">c<sub>2</sub></span> / <span class="id" type="var">pe_st'</span> \\ <span class="id" type="var">c<sub>2</sub>'</span> / <span class="id" type="var">pe_st''</span> / <span class="id" type="var">c''</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">c<sub>1</sub></span> ;; <span class="id" type="var">c<sub>2</sub></span>) / <span class="id" type="var">pe_st</span> \\ (<span class="id" type="var">c<sub>1</sub>'</span> ;; <span class="id" type="var">c<sub>2</sub>'</span>) / <span class="id" type="var">pe_st''</span> / <span class="id" type="var">c''</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">PE_IfTrue</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">pe_st</span> <span class="id" type="var">pe_st'</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">c<sub>1</sub>'</span> <span class="id" type="var">c''</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">pe_bexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">b<sub>1</sub></span> = <span class="id" type="var">BTrue</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">c<sub>1</sub></span> / <span class="id" type="var">pe_st</span> \\ <span class="id" type="var">c<sub>1</sub>'</span> / <span class="id" type="var">pe_st'</span> / <span class="id" type="var">c''</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">TEST</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">THEN</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">ELSE</span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">FI</span>) / <span class="id" type="var">pe_st</span> \\ <span class="id" type="var">c<sub>1</sub>'</span> / <span class="id" type="var">pe_st'</span> / <span class="id" type="var">c''</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">PE_IfFalse</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">pe_st</span> <span class="id" type="var">pe_st'</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">c<sub>2</sub>'</span> <span class="id" type="var">c''</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">pe_bexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">b<sub>1</sub></span> = <span class="id" type="var">BFalse</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">c<sub>2</sub></span> / <span class="id" type="var">pe_st</span> \\ <span class="id" type="var">c<sub>2</sub>'</span> / <span class="id" type="var">pe_st'</span> / <span class="id" type="var">c''</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">TEST</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">THEN</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">ELSE</span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">FI</span>) / <span class="id" type="var">pe_st</span> \\ <span class="id" type="var">c<sub>2</sub>'</span> / <span class="id" type="var">pe_st'</span> / <span class="id" type="var">c''</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">PE_If</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">pe_st</span> <span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">c<sub>1</sub>'</span> <span class="id" type="var">c<sub>2</sub>'</span> <span class="id" type="var">c''</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">pe_bexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">b<sub>1</sub></span> ≠ <span class="id" type="var">BTrue</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">pe_bexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">b<sub>1</sub></span> ≠ <span class="id" type="var">BFalse</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">c<sub>1</sub></span> / <span class="id" type="var">pe_st</span> \\ <span class="id" type="var">c<sub>1</sub>'</span> / <span class="id" type="var">pe_st<sub>1</sub></span> / <span class="id" type="var">c''</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">c<sub>2</sub></span> / <span class="id" type="var">pe_st</span> \\ <span class="id" type="var">c<sub>2</sub>'</span> / <span class="id" type="var">pe_st<sub>2</sub></span> / <span class="id" type="var">c''</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">TEST</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">THEN</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">ELSE</span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">FI</span>) / <span class="id" type="var">pe_st</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\\ (<span class="id" type="var">TEST</span> <span class="id" type="var">pe_bexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">b<sub>1</sub></span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">THEN</span> <span class="id" type="var">c<sub>1</sub>'</span> ;; <span class="id" type="var">assign</span> <span class="id" type="var">pe_st<sub>1</sub></span> (<span class="id" type="var">pe_compare</span> <span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">ELSE</span> <span class="id" type="var">c<sub>2</sub>'</span> ;; <span class="id" type="var">assign</span> <span class="id" type="var">pe_st<sub>2</sub></span> (<span class="id" type="var">pe_compare</span> <span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span>) <span class="id" type="var">FI</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/ <span class="id" type="var">pe_removes</span> <span class="id" type="var">pe_st<sub>1</sub></span> (<span class="id" type="var">pe_compare</span> <span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/ <span class="id" type="var">c''</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">PE_WhileFalse</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">pe_st</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">c<sub>1</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">pe_bexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">b<sub>1</sub></span> = <span class="id" type="var">BFalse</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">WHILE</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">DO</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">END</span>) / <span class="id" type="var">pe_st</span> \\ <span class="id" type="var">SKIP</span> / <span class="id" type="var">pe_st</span> / <span class="id" type="var">SKIP</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">PE_WhileTrue</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">pe_st</span> <span class="id" type="var">pe_st'</span> <span class="id" type="var">pe_st''</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>1</sub>'</span> <span class="id" type="var">c<sub>2</sub>'</span> <span class="id" type="var">c<sub>2</sub>''</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">pe_bexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">b<sub>1</sub></span> = <span class="id" type="var">BTrue</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">c<sub>1</sub></span> / <span class="id" type="var">pe_st</span> \\ <span class="id" type="var">c<sub>1</sub>'</span> / <span class="id" type="var">pe_st'</span> / <span class="id" type="var">SKIP</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">WHILE</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">DO</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">END</span>) / <span class="id" type="var">pe_st'</span> \\ <span class="id" type="var">c<sub>2</sub>'</span> / <span class="id" type="var">pe_st''</span> / <span class="id" type="var">c<sub>2</sub>''</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">pe_compare</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">pe_st''</span> ≠ [] →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">WHILE</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">DO</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">END</span>) / <span class="id" type="var">pe_st</span> \\ (<span class="id" type="var">c<sub>1</sub>'</span>;;<span class="id" type="var">c<sub>2</sub>'</span>) / <span class="id" type="var">pe_st''</span> / <span class="id" type="var">c<sub>2</sub>''</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">PE_While</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">pe_st</span> <span class="id" type="var">pe_st'</span> <span class="id" type="var">pe_st''</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>1</sub>'</span> <span class="id" type="var">c<sub>2</sub>'</span> <span class="id" type="var">c<sub>2</sub>''</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">pe_bexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">b<sub>1</sub></span> ≠ <span class="id" type="var">BFalse</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">pe_bexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">b<sub>1</sub></span> ≠ <span class="id" type="var">BTrue</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">c<sub>1</sub></span> / <span class="id" type="var">pe_st</span> \\ <span class="id" type="var">c<sub>1</sub>'</span> / <span class="id" type="var">pe_st'</span> / <span class="id" type="var">SKIP</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">WHILE</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">DO</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">END</span>) / <span class="id" type="var">pe_st'</span> \\ <span class="id" type="var">c<sub>2</sub>'</span> / <span class="id" type="var">pe_st''</span> / <span class="id" type="var">c<sub>2</sub>''</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">pe_compare</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">pe_st''</span> ≠ [] →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">c<sub>2</sub>''</span> = <span class="id" type="var">SKIP</span>%<span class="id" type="var">imp</span> ∨ <span class="id" type="var">c<sub>2</sub>''</span> = <span class="id" type="var">WHILE</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">DO</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">END</span>%<span class="id" type="var">imp</span>) →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">WHILE</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">DO</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">END</span>) / <span class="id" type="var">pe_st</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\\ (<span class="id" type="var">TEST</span> <span class="id" type="var">pe_bexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">b<sub>1</sub></span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">THEN</span> <span class="id" type="var">c<sub>1</sub>'</span>;; <span class="id" type="var">c<sub>2</sub>'</span>;; <span class="id" type="var">assign</span> <span class="id" type="var">pe_st''</span> (<span class="id" type="var">pe_compare</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">pe_st''</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">ELSE</span> <span class="id" type="var">assign</span> <span class="id" type="var">pe_st</span> (<span class="id" type="var">pe_compare</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">pe_st''</span>) <span class="id" type="var">FI</span>)%<span class="id" type="var">imp</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/ <span class="id" type="var">pe_removes</span> <span class="id" type="var">pe_st</span> (<span class="id" type="var">pe_compare</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">pe_st''</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/ <span class="id" type="var">c<sub>2</sub>''</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">PE_WhileFixedEnd</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">pe_st</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">c<sub>1</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">pe_bexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">b<sub>1</sub></span> ≠ <span class="id" type="var">BFalse</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">WHILE</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">DO</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">END</span>) / <span class="id" type="var">pe_st</span> \\ <span class="id" type="var">SKIP</span> / <span class="id" type="var">pe_st</span> / (<span class="id" type="var">WHILE</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">DO</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">END</span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">PE_WhileFixedLoop</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">pe_st</span> <span class="id" type="var">pe_st'</span> <span class="id" type="var">pe_st''</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>1</sub>'</span> <span class="id" type="var">c<sub>2</sub>'</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">pe_bexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">b<sub>1</sub></span> = <span class="id" type="var">BTrue</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">c<sub>1</sub></span> / <span class="id" type="var">pe_st</span> \\ <span class="id" type="var">c<sub>1</sub>'</span> / <span class="id" type="var">pe_st'</span> / <span class="id" type="var">SKIP</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">WHILE</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">DO</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">END</span>) / <span class="id" type="var">pe_st'</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\\ <span class="id" type="var">c<sub>2</sub>'</span> / <span class="id" type="var">pe_st''</span> / (<span class="id" type="var">WHILE</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">DO</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">END</span>) →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">pe_compare</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">pe_st''</span> = [] →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">WHILE</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">DO</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">END</span>) / <span class="id" type="var">pe_st</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\\ (<span class="id" type="var">WHILE</span> <span class="id" type="var">BTrue</span> <span class="id" type="var">DO</span> <span class="id" type="var">SKIP</span> <span class="id" type="var">END</span>) / <span class="id" type="var">pe_st</span> / <span class="id" type="var">SKIP</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">(*&nbsp;因为这里是一个无限循环，我们实际上应该开始抛弃剩下的程序：<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(WHILE&nbsp;b<sub>1</sub>&nbsp;DO&nbsp;c<sub>1</sub>&nbsp;END)&nbsp;/&nbsp;pe_st<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\\&nbsp;SKIP&nbsp;/&nbsp;pe_st&nbsp;/&nbsp;(WHILE&nbsp;BTrue&nbsp;DO&nbsp;SKIP&nbsp;END)&nbsp;*)</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">PE_WhileFixed</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">pe_st</span> <span class="id" type="var">pe_st'</span> <span class="id" type="var">pe_st''</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>1</sub>'</span> <span class="id" type="var">c<sub>2</sub>'</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">pe_bexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">b<sub>1</sub></span> ≠ <span class="id" type="var">BFalse</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">pe_bexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">b<sub>1</sub></span> ≠ <span class="id" type="var">BTrue</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">c<sub>1</sub></span> / <span class="id" type="var">pe_st</span> \\ <span class="id" type="var">c<sub>1</sub>'</span> / <span class="id" type="var">pe_st'</span> / <span class="id" type="var">SKIP</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">WHILE</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">DO</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">END</span>) / <span class="id" type="var">pe_st'</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\\ <span class="id" type="var">c<sub>2</sub>'</span> / <span class="id" type="var">pe_st''</span> / (<span class="id" type="var">WHILE</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">DO</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">END</span>) →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">pe_compare</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">pe_st''</span> = [] →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">WHILE</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">DO</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">END</span>) / <span class="id" type="var">pe_st</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\\ (<span class="id" type="var">WHILE</span> <span class="id" type="var">pe_bexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">DO</span> <span class="id" type="var">c<sub>1</sub>'</span>;; <span class="id" type="var">c<sub>2</sub>'</span> <span class="id" type="var">END</span>) / <span class="id" type="var">pe_st</span> / <span class="id" type="var">SKIP</span><br/>
<br/>
&nbsp;&nbsp;<span class="id" type="keyword">where</span> "c<sub>1</sub> '/' st '\\' c<sub>1</sub>' '/' st' '/' c''" := (<span class="id" type="var">pe_com</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">st</span> <span class="id" type="var">c<sub>1</sub>'</span> <span class="id" type="var">st'</span> <span class="id" type="var">c''</span>).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Hint</span> <span class="id" type="var">Constructors</span> <span class="id" type="var">pe_com</span>.<br/>
</div>

<div class="doc">
<a name="lab587"></a><h2 class="section">例子</h2>

</div>
<div class="code code-space">

<br/>
<span class="id" type="keyword">Ltac</span> <span class="id" type="var">step</span> <span class="id" type="var">i</span> :=<br/>
&nbsp;&nbsp;(<span class="id" type="tactic">eapply</span> <span class="id" type="var">i</span>; <span class="id" type="tactic">intuition</span> <span class="id" type="tactic">eauto</span>; <span class="id" type="tactic">try</span> <span class="id" type="var">solve_by_invert</span>);<br/>
&nbsp;&nbsp;<span class="id" type="tactic">repeat</span> (<span class="id" type="tactic">try</span> <span class="id" type="tactic">eapply</span> <span class="id" type="var">PE_Seq</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">try</span> (<span class="id" type="tactic">eapply</span> <span class="id" type="var">PE_AssStatic</span>; <span class="id" type="tactic">simpl</span>; <span class="id" type="tactic">reflexivity</span>);<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">try</span> (<span class="id" type="tactic">eapply</span> <span class="id" type="var">PE_AssDynamic</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[ <span class="id" type="tactic">simpl</span>; <span class="id" type="tactic">reflexivity</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| <span class="id" type="tactic">intuition</span> <span class="id" type="tactic">eauto</span>; <span class="id" type="var">solve_by_invert</span>])).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Definition</span> <span class="id" type="var">square_loop</span>: <span class="id" type="var">com</span> :=<br/>
&nbsp;&nbsp;(<span class="id" type="var">WHILE</span> 1 ≤ <span class="id" type="var">X</span> <span class="id" type="var">DO</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Y</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">Y</span> * <span class="id" type="var">Y</span>;;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">X</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">X</span> - 1<br/>
&nbsp;&nbsp;<span class="id" type="var">END</span>)%<span class="id" type="var">imp</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">pe_loop_example1</span>:<br/>
&nbsp;&nbsp;<span class="id" type="var">square_loop</span> / []<br/>
&nbsp;&nbsp;\\ (<span class="id" type="var">WHILE</span> 1 ≤ <span class="id" type="var">X</span> <span class="id" type="var">DO</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">Y</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">Y</span> * <span class="id" type="var">Y</span>;;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">X</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">X</span> - 1);; <span class="id" type="var">SKIP</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">END</span>)%<span class="id" type="var">imp</span> / [] / <span class="id" type="var">SKIP</span>.<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="var">erewrite</span> <span class="id" type="var">f_equal2</span> <span class="id" type="keyword">with</span> (<span class="id" type="var">f</span> := <span class="id" type="keyword">fun</span> <span class="id" type="var">c</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">_</span> / <span class="id" type="var">_</span> \\ <span class="id" type="var">c</span> / <span class="id" type="var">st</span> / <span class="id" type="var">SKIP</span>).<br/>
&nbsp;&nbsp;<span class="id" type="var">step</span> <span class="id" type="var">PE_WhileFixed</span>. <span class="id" type="var">step</span> <span class="id" type="var">PE_WhileFixedEnd</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">reflexivity</span>. <span class="id" type="tactic">reflexivity</span>. <span class="id" type="keyword">Qed</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">pe_loop_example2</span>:<br/>
&nbsp;&nbsp;(<span class="id" type="var">X</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> 3;; <span class="id" type="var">square_loop</span>)%<span class="id" type="var">imp</span> / []<br/>
&nbsp;&nbsp;\\ (<span class="id" type="var">SKIP</span>;;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">Y</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">Y</span> * <span class="id" type="var">Y</span>;; <span class="id" type="var">SKIP</span>);;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">Y</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">Y</span> * <span class="id" type="var">Y</span>;; <span class="id" type="var">SKIP</span>);;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">Y</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">Y</span> * <span class="id" type="var">Y</span>;; <span class="id" type="var">SKIP</span>);;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">SKIP</span>)%<span class="id" type="var">imp</span> / [(<span class="id" type="var">X</span>,0)] / <span class="id" type="var">SKIP</span>%<span class="id" type="var">imp</span>.<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="var">erewrite</span> <span class="id" type="var">f_equal2</span> <span class="id" type="keyword">with</span> (<span class="id" type="var">f</span> := <span class="id" type="keyword">fun</span> <span class="id" type="var">c</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">_</span> / <span class="id" type="var">_</span> \\ <span class="id" type="var">c</span> / <span class="id" type="var">st</span> / <span class="id" type="var">SKIP</span>).<br/>
&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">PE_Seq</span>. <span class="id" type="tactic">eapply</span> <span class="id" type="var">PE_AssStatic</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;<span class="id" type="var">step</span> <span class="id" type="var">PE_WhileTrue</span>.<br/>
&nbsp;&nbsp;<span class="id" type="var">step</span> <span class="id" type="var">PE_WhileTrue</span>.<br/>
&nbsp;&nbsp;<span class="id" type="var">step</span> <span class="id" type="var">PE_WhileTrue</span>.<br/>
&nbsp;&nbsp;<span class="id" type="var">step</span> <span class="id" type="var">PE_WhileFalse</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span>. <span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span>. <span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">reflexivity</span>. <span class="id" type="tactic">reflexivity</span>. <span class="id" type="keyword">Qed</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">pe_loop_example3</span>:<br/>
&nbsp;&nbsp;(<span class="id" type="var">Z</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> 3;; <span class="id" type="var">subtract_slowly</span>) / []<br/>
&nbsp;&nbsp;\\ (<span class="id" type="var">SKIP</span>;;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">TEST</span> ~(<span class="id" type="var">X</span> = 0) <span class="id" type="var">THEN</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">SKIP</span>;; <span class="id" type="var">X</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">X</span> - 1);;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">TEST</span> ~(<span class="id" type="var">X</span> = 0) <span class="id" type="var">THEN</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">SKIP</span>;; <span class="id" type="var">X</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">X</span> - 1);;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">TEST</span> ~(<span class="id" type="var">X</span> = 0) <span class="id" type="var">THEN</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">SKIP</span>;; <span class="id" type="var">X</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">X</span> - 1);;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">WHILE</span> ~(<span class="id" type="var">X</span> = 0) <span class="id" type="var">DO</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">SKIP</span>;; <span class="id" type="var">X</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">X</span> - 1);; <span class="id" type="var">SKIP</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">END</span>;;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">SKIP</span>;; <span class="id" type="var">Z</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> 0<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">ELSE</span> <span class="id" type="var">SKIP</span>;; <span class="id" type="var">Z</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> 1 <span class="id" type="var">FI</span>;; <span class="id" type="var">SKIP</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">ELSE</span> <span class="id" type="var">SKIP</span>;; <span class="id" type="var">Z</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> 2 <span class="id" type="var">FI</span>;; <span class="id" type="var">SKIP</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">ELSE</span> <span class="id" type="var">SKIP</span>;; <span class="id" type="var">Z</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> 3 <span class="id" type="var">FI</span>)%<span class="id" type="var">imp</span> / [] / <span class="id" type="var">SKIP</span>.<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="var">erewrite</span> <span class="id" type="var">f_equal2</span> <span class="id" type="keyword">with</span> (<span class="id" type="var">f</span> := <span class="id" type="keyword">fun</span> <span class="id" type="var">c</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">_</span> / <span class="id" type="var">_</span> \\ <span class="id" type="var">c</span> / <span class="id" type="var">st</span> / <span class="id" type="var">SKIP</span>).<br/>
&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">PE_Seq</span>. <span class="id" type="tactic">eapply</span> <span class="id" type="var">PE_AssStatic</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;<span class="id" type="var">step</span> <span class="id" type="var">PE_While</span>.<br/>
&nbsp;&nbsp;<span class="id" type="var">step</span> <span class="id" type="var">PE_While</span>.<br/>
&nbsp;&nbsp;<span class="id" type="var">step</span> <span class="id" type="var">PE_While</span>.<br/>
&nbsp;&nbsp;<span class="id" type="var">step</span> <span class="id" type="var">PE_WhileFixed</span>.<br/>
&nbsp;&nbsp;<span class="id" type="var">step</span> <span class="id" type="var">PE_WhileFixedEnd</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">reflexivity</span>. <span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span>. <span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span>. <span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">reflexivity</span>. <span class="id" type="tactic">reflexivity</span>. <span class="id" type="keyword">Qed</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">pe_loop_example4</span>:<br/>
&nbsp;&nbsp;(<span class="id" type="var">X</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> 0;;<br/>
&nbsp;&nbsp;&nbsp;<span class="id" type="var">WHILE</span> <span class="id" type="var">X</span> ≤ 2 <span class="id" type="var">DO</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">X</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> 1 - <span class="id" type="var">X</span><br/>
&nbsp;&nbsp;&nbsp;<span class="id" type="var">END</span>)%<span class="id" type="var">imp</span> / [] \\ (<span class="id" type="var">SKIP</span>;; <span class="id" type="var">WHILE</span> <span class="id" type="var">true</span> <span class="id" type="var">DO</span> <span class="id" type="var">SKIP</span> <span class="id" type="var">END</span>)%<span class="id" type="var">imp</span> / [(<span class="id" type="var">X</span>,0)] / <span class="id" type="var">SKIP</span>.<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="var">erewrite</span> <span class="id" type="var">f_equal2</span> <span class="id" type="keyword">with</span> (<span class="id" type="var">f</span> := <span class="id" type="keyword">fun</span> <span class="id" type="var">c</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">_</span> / <span class="id" type="var">_</span> \\ <span class="id" type="var">c</span> / <span class="id" type="var">st</span> / <span class="id" type="var">SKIP</span>).<br/>
&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">PE_Seq</span>. <span class="id" type="tactic">eapply</span> <span class="id" type="var">PE_AssStatic</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;<span class="id" type="var">step</span> <span class="id" type="var">PE_WhileFixedLoop</span>.<br/>
&nbsp;&nbsp;<span class="id" type="var">step</span> <span class="id" type="var">PE_WhileTrue</span>.<br/>
&nbsp;&nbsp;<span class="id" type="var">step</span> <span class="id" type="var">PE_WhileFixedEnd</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span>. <span class="id" type="tactic">reflexivity</span>. <span class="id" type="tactic">reflexivity</span>. <span class="id" type="tactic">reflexivity</span>. <span class="id" type="keyword">Qed</span>.<br/>
</div>

<div class="doc">
<a name="lab588"></a><h2 class="section">正确性</h2>

<div class="paragraph"> </div>

 由于部分求值器可以展开一个循环 n 次，其中 n 是一个大于一的有限整数，为了证明其
    正确性我们需要对循环体动态求值的次数进行归纳，而非结构地对动态求值归纳。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Reserved Notation</span> "c<sub>1</sub> '/' st '\\' st' '#' n"<br/>
&nbsp;&nbsp;(<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 40, <span class="id" type="var">st</span> <span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 39, <span class="id" type="var">st'</span> <span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 39).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Inductive</span> <span class="id" type="var">ceval_count</span> : <span class="id" type="var">com</span> → <span class="id" type="var">state</span> → <span class="id" type="var">state</span> → <span class="id" type="var">nat</span> → <span class="id" type="keyword">Prop</span> :=<br/>
&nbsp;&nbsp;| <span class="id" type="var">E'Skip</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">SKIP</span> / <span class="id" type="var">st</span> \\ <span class="id" type="var">st</span> # 0<br/>
&nbsp;&nbsp;| <span class="id" type="var">E'Ass</span>  : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">a<sub>1</sub></span> <span class="id" type="var">n</span> <span class="id" type="var">l</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">aeval</span> <span class="id" type="var">st</span> <span class="id" type="var">a<sub>1</sub></span> = <span class="id" type="var">n</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">l</span> <span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>:</span>:</span>=</span> <span class="id" type="var">a<sub>1</sub></span>) / <span class="id" type="var">st</span> \\ (<span class="id" type="var">t_update</span> <span class="id" type="var">st</span> <span class="id" type="var">l</span> <span class="id" type="var">n</span>) # 0<br/>
&nbsp;&nbsp;| <span class="id" type="var">E'Seq</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">st''</span> <span class="id" type="var">n<sub>1</sub></span> <span class="id" type="var">n<sub>2</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">c<sub>1</sub></span> / <span class="id" type="var">st</span>  \\ <span class="id" type="var">st'</span>  # <span class="id" type="var">n<sub>1</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">c<sub>2</sub></span> / <span class="id" type="var">st'</span> \\ <span class="id" type="var">st''</span> # <span class="id" type="var">n<sub>2</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">c<sub>1</sub></span> ;; <span class="id" type="var">c<sub>2</sub></span>) / <span class="id" type="var">st</span> \\ <span class="id" type="var">st''</span> # (<span class="id" type="var">n<sub>1</sub></span> + <span class="id" type="var">n<sub>2</sub></span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">E'IfTrue</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">n</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">beval</span> <span class="id" type="var">st</span> <span class="id" type="var">b<sub>1</sub></span> = <span class="id" type="var">true</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">c<sub>1</sub></span> / <span class="id" type="var">st</span> \\ <span class="id" type="var">st'</span> # <span class="id" type="var">n</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">TEST</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">THEN</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">ELSE</span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">FI</span>) / <span class="id" type="var">st</span> \\ <span class="id" type="var">st'</span> # <span class="id" type="var">n</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">E'IfFalse</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">n</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">beval</span> <span class="id" type="var">st</span> <span class="id" type="var">b<sub>1</sub></span> = <span class="id" type="var">false</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">c<sub>2</sub></span> / <span class="id" type="var">st</span> \\ <span class="id" type="var">st'</span> # <span class="id" type="var">n</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">TEST</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">THEN</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">ELSE</span> <span class="id" type="var">c<sub>2</sub></span> <span class="id" type="var">FI</span>) / <span class="id" type="var">st</span> \\ <span class="id" type="var">st'</span> # <span class="id" type="var">n</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">E'WhileFalse</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">st</span> <span class="id" type="var">c<sub>1</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">beval</span> <span class="id" type="var">st</span> <span class="id" type="var">b<sub>1</sub></span> = <span class="id" type="var">false</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">WHILE</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">DO</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">END</span>) / <span class="id" type="var">st</span> \\ <span class="id" type="var">st</span> # 0<br/>
&nbsp;&nbsp;| <span class="id" type="var">E'WhileTrue</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">st''</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">n<sub>1</sub></span> <span class="id" type="var">n<sub>2</sub></span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">beval</span> <span class="id" type="var">st</span> <span class="id" type="var">b<sub>1</sub></span> = <span class="id" type="var">true</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">c<sub>1</sub></span> / <span class="id" type="var">st</span> \\ <span class="id" type="var">st'</span> # <span class="id" type="var">n<sub>1</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">WHILE</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">DO</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">END</span>) / <span class="id" type="var">st'</span> \\ <span class="id" type="var">st''</span> # <span class="id" type="var">n<sub>2</sub></span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">WHILE</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">DO</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">END</span>) / <span class="id" type="var">st</span> \\ <span class="id" type="var">st''</span> # <span class="id" type="var">S</span> (<span class="id" type="var">n<sub>1</sub></span> + <span class="id" type="var">n<sub>2</sub></span>)<br/>
<br/>
&nbsp;&nbsp;<span class="id" type="keyword">where</span> "c<sub>1</sub> '/' st '\\' st' # n" := (<span class="id" type="var">ceval_count</span> <span class="id" type="var">c<sub>1</sub></span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">n</span>).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Hint</span> <span class="id" type="var">Constructors</span> <span class="id" type="var">ceval_count</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">ceval_count_complete</span>: <span style='font-size:120%;'>&forall;</span><span class="id" type="var">c</span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span>,<br/>
&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">c</span> ]⇒ <span class="id" type="var">st'</span> → <span style='font-size:120%;'>&exist;</span><span class="id" type="var">n</span>, <span class="id" type="var">c</span> / <span class="id" type="var">st</span> \\ <span class="id" type="var">st'</span> # <span class="id" type="var">n</span>.<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">c</span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">Heval</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">induction</span> <span class="id" type="var">Heval</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">try</span> <span class="id" type="tactic">inversion</span> <span class="id" type="var">IHHeval1</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">try</span> <span class="id" type="tactic">inversion</span> <span class="id" type="var">IHHeval2</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">try</span> <span class="id" type="tactic">inversion</span> <span class="id" type="var">IHHeval</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eauto</span>. <span class="id" type="keyword">Qed</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">ceval_count_sound</span>: <span style='font-size:120%;'>&forall;</span><span class="id" type="var">c</span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">n</span>,<br/>
&nbsp;&nbsp;<span class="id" type="var">c</span> / <span class="id" type="var">st</span> \\ <span class="id" type="var">st'</span> # <span class="id" type="var">n</span> → <span class="id" type="var">st</span> =[ <span class="id" type="var">c</span> ]⇒ <span class="id" type="var">st'</span>.<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">c</span> <span class="id" type="var">st</span> <span class="id" type="var">st'</span> <span class="id" type="var">n</span> <span class="id" type="var">Heval</span>. <span class="id" type="tactic">induction</span> <span class="id" type="var">Heval</span>; <span class="id" type="tactic">eauto</span>. <span class="id" type="keyword">Qed</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">pe_compare_nil_lookup</span>: <span style='font-size:120%;'>&forall;</span><span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span>,<br/>
&nbsp;&nbsp;<span class="id" type="var">pe_compare</span> <span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span> = [] →<br/>
&nbsp;&nbsp;<span style='font-size:120%;'>&forall;</span><span class="id" type="var">V</span>, <span class="id" type="var">pe_lookup</span> <span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">V</span> = <span class="id" type="var">pe_lookup</span> <span class="id" type="var">pe_st<sub>2</sub></span> <span class="id" type="var">V</span>.<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span> <span class="id" type="var">H</span> <span class="id" type="var">V</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">apply</span> (<span class="id" type="var">pe_compare_correct</span> <span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span> <span class="id" type="var">V</span>).<br/>
&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> <span class="id" type="var">H</span>. <span class="id" type="tactic">intro</span>. <span class="id" type="tactic">inversion</span> <span class="id" type="var">H<sub>0</sub></span>. <span class="id" type="keyword">Qed</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">pe_compare_nil_update</span>: <span style='font-size:120%;'>&forall;</span><span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span>,<br/>
&nbsp;&nbsp;<span class="id" type="var">pe_compare</span> <span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span> = [] →<br/>
&nbsp;&nbsp;<span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span>, <span class="id" type="var">pe_update</span> <span class="id" type="var">st</span> <span class="id" type="var">pe_st<sub>1</sub></span> = <span class="id" type="var">pe_update</span> <span class="id" type="var">st</span> <span class="id" type="var">pe_st<sub>2</sub></span>.<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">pe_st<sub>1</sub></span> <span class="id" type="var">pe_st<sub>2</sub></span> <span class="id" type="var">H</span> <span class="id" type="var">st</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">functional_extensionality</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">V</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> !<span class="id" type="var">pe_update_correct</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">pe_compare_nil_lookup</span> <span class="id" type="keyword">with</span> (<span class="id" type="var">V</span>:=<span class="id" type="var">V</span>) <span class="id" type="keyword">in</span> <span class="id" type="var">H</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> <span class="id" type="var">H</span>. <span class="id" type="tactic">reflexivity</span>. <span class="id" type="keyword">Qed</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Reserved Notation</span> "c' '/' pe_st' '/' c'' '/' st '\\' st'' '#' n"<br/>
&nbsp;&nbsp;(<span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 40, <span class="id" type="var">pe_st'</span> <span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 39, <span class="id" type="var">c''</span> <span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 39,<br/>
&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> <span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 39, <span class="id" type="var">st''</span> <span class="id" type="tactic">at</span> <span class="id" type="var">level</span> 39).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Inductive</span> <span class="id" type="var">pe_ceval_count</span> (<span class="id" type="var">c'</span>:<span class="id" type="var">com</span>) (<span class="id" type="var">pe_st'</span>:<span class="id" type="var">pe_state</span>) (<span class="id" type="var">c''</span>:<span class="id" type="var">com</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">st</span>:<span class="id" type="var">state</span>) (<span class="id" type="var">st''</span>:<span class="id" type="var">state</span>) (<span class="id" type="var">n</span>:<span class="id" type="var">nat</span>) : <span class="id" type="keyword">Prop</span> :=<br/>
&nbsp;&nbsp;| <span class="id" type="var">pe_ceval_count_intro</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st'</span> <span class="id" type="var">n'</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">st</span> =[ <span class="id" type="var">c'</span> ]⇒ <span class="id" type="var">st'</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">c''</span> / <span class="id" type="var">pe_update</span> <span class="id" type="var">st'</span> <span class="id" type="var">pe_st'</span> \\ <span class="id" type="var">st''</span> # <span class="id" type="var">n'</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">n'</span> ≤ <span class="id" type="var">n</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">c'</span> / <span class="id" type="var">pe_st'</span> / <span class="id" type="var">c''</span> / <span class="id" type="var">st</span> \\ <span class="id" type="var">st''</span> # <span class="id" type="var">n</span><br/>
&nbsp;&nbsp;<span class="id" type="keyword">where</span> "c' '/' pe_st' '/' c'' '/' st '\\' st'' '#' n" :=<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">pe_ceval_count</span> <span class="id" type="var">c'</span> <span class="id" type="var">pe_st'</span> <span class="id" type="var">c''</span> <span class="id" type="var">st</span> <span class="id" type="var">st''</span> <span class="id" type="var">n</span>).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Hint</span> <span class="id" type="var">Constructors</span> <span class="id" type="var">pe_ceval_count</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Lemma</span> <span class="id" type="var">pe_ceval_count_le</span>: <span style='font-size:120%;'>&forall;</span><span class="id" type="var">c'</span> <span class="id" type="var">pe_st'</span> <span class="id" type="var">c''</span> <span class="id" type="var">st</span> <span class="id" type="var">st''</span> <span class="id" type="var">n</span> <span class="id" type="var">n'</span>,<br/>
&nbsp;&nbsp;<span class="id" type="var">n'</span> ≤ <span class="id" type="var">n</span> →<br/>
&nbsp;&nbsp;<span class="id" type="var">c'</span> / <span class="id" type="var">pe_st'</span> / <span class="id" type="var">c''</span> / <span class="id" type="var">st</span> \\ <span class="id" type="var">st''</span> # <span class="id" type="var">n'</span> →<br/>
&nbsp;&nbsp;<span class="id" type="var">c'</span> / <span class="id" type="var">pe_st'</span> / <span class="id" type="var">c''</span> / <span class="id" type="var">st</span> \\ <span class="id" type="var">st''</span> # <span class="id" type="var">n</span>.<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">c'</span> <span class="id" type="var">pe_st'</span> <span class="id" type="var">c''</span> <span class="id" type="var">st</span> <span class="id" type="var">st''</span> <span class="id" type="var">n</span> <span class="id" type="var">n'</span> <span class="id" type="var">Hle</span> <span class="id" type="var">H</span>. <span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span>.<br/>
&nbsp;&nbsp;<span class="id" type="var">econstructor</span>; <span class="id" type="tactic">try</span> <span class="id" type="var">eassumption</span>. <span class="id" type="tactic">omega</span>. <span class="id" type="keyword">Qed</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">pe_com_complete</span>:<br/>
&nbsp;&nbsp;<span style='font-size:120%;'>&forall;</span><span class="id" type="var">c</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">pe_st'</span> <span class="id" type="var">c'</span> <span class="id" type="var">c''</span>, <span class="id" type="var">c</span> / <span class="id" type="var">pe_st</span> \\ <span class="id" type="var">c'</span> / <span class="id" type="var">pe_st'</span> / <span class="id" type="var">c''</span> →<br/>
&nbsp;&nbsp;<span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">st''</span> <span class="id" type="var">n</span>,<br/>
&nbsp;&nbsp;(<span class="id" type="var">c</span> / <span class="id" type="var">pe_update</span> <span class="id" type="var">st</span> <span class="id" type="var">pe_st</span> \\ <span class="id" type="var">st''</span> # <span class="id" type="var">n</span>) →<br/>
&nbsp;&nbsp;(<span class="id" type="var">c'</span> / <span class="id" type="var">pe_st'</span> / <span class="id" type="var">c''</span> / <span class="id" type="var">st</span> \\ <span class="id" type="var">st''</span> # <span class="id" type="var">n</span>).<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">c</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">pe_st'</span> <span class="id" type="var">c'</span> <span class="id" type="var">c''</span> <span class="id" type="var">Hpe</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">induction</span> <span class="id" type="var">Hpe</span>; <span class="id" type="tactic">intros</span> <span class="id" type="var">st</span> <span class="id" type="var">st''</span> <span class="id" type="var">n</span> <span class="id" type="var">Heval</span>;<br/>
&nbsp;&nbsp;<span class="id" type="tactic">try</span> (<span class="id" type="tactic">inversion</span> <span class="id" type="var">Heval</span>; <span class="id" type="tactic">subst</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">try</span> (<span class="id" type="tactic">rewrite</span> → <span class="id" type="var">pe_bexp_correct</span>, → <span class="id" type="var">H</span> <span class="id" type="keyword">in</span> *; <span class="id" type="var">solve_by_invert</span>);<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[]);<br/>
&nbsp;&nbsp;<span class="id" type="tactic">eauto</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;PE_AssStatic&nbsp;*)</span> <span class="id" type="var">econstructor</span>. <span class="id" type="var">econstructor</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> → <span class="id" type="var">pe_aexp_correct</span>. <span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">pe_update_update_add</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> → <span class="id" type="var">H</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">E'Skip</span>. <span class="id" type="tactic">auto</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;PE_AssDynamic&nbsp;*)</span> <span class="id" type="var">econstructor</span>. <span class="id" type="var">econstructor</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> → <span class="id" type="var">pe_aexp_correct</span>. <span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">pe_update_update_remove</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">E'Skip</span>. <span class="id" type="tactic">auto</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;PE_Seq&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">edestruct</span> <span class="id" type="var">IHHpe1</span> <span class="id" type="keyword">as</span> [? ? ? <span class="id" type="var">Hskip</span> ?]. <span class="id" type="var">eassumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">Hskip</span>. <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">edestruct</span> <span class="id" type="var">IHHpe2</span>. <span class="id" type="var">eassumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">econstructor</span>; <span class="id" type="tactic">eauto</span>. <span class="id" type="tactic">omega</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;PE_If&nbsp;*)</span> <span class="id" type="tactic">inversion</span> <span class="id" type="var">Heval</span>; <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;E'IfTrue&nbsp;*)</span> <span class="id" type="var">edestruct</span> <span class="id" type="var">IHHpe1</span>. <span class="id" type="var">eassumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">econstructor</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">E_IfTrue</span>. <span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">pe_bexp_correct</span>. <span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">E_Seq</span>. <span class="id" type="var">eassumption</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">eval_assign</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">assign_removes</span>. <span class="id" type="var">eassumption</span>. <span class="id" type="var">eassumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;E_IfFalse&nbsp;*)</span> <span class="id" type="var">edestruct</span> <span class="id" type="var">IHHpe2</span>. <span class="id" type="var">eassumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">econstructor</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">E_IfFalse</span>. <span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">pe_bexp_correct</span>. <span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">E_Seq</span>. <span class="id" type="var">eassumption</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">eval_assign</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> → <span class="id" type="var">pe_compare_update</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">assign_removes</span>. <span class="id" type="var">eassumption</span>. <span class="id" type="var">eassumption</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;PE_WhileTrue&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">edestruct</span> <span class="id" type="var">IHHpe1</span> <span class="id" type="keyword">as</span> [? ? ? <span class="id" type="var">Hskip</span> ?]. <span class="id" type="var">eassumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">Hskip</span>. <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">edestruct</span> <span class="id" type="var">IHHpe2</span>. <span class="id" type="var">eassumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">econstructor</span>; <span class="id" type="tactic">eauto</span>. <span class="id" type="tactic">omega</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;PE_While&nbsp;*)</span> <span class="id" type="tactic">inversion</span> <span class="id" type="var">Heval</span>; <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;E_WhileFalse&nbsp;*)</span> <span class="id" type="var">econstructor</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">E_IfFalse</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">pe_bexp_correct</span>. <span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">eval_assign</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">assign_removes</span>. <span class="id" type="tactic">inversion</span> <span class="id" type="var">H<sub>2</sub></span>; <span class="id" type="tactic">subst</span>; <span class="id" type="tactic">auto</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">auto</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;E_WhileTrue&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">edestruct</span> <span class="id" type="var">IHHpe1</span> <span class="id" type="keyword">as</span> [? ? ? <span class="id" type="var">Hskip</span> ?]. <span class="id" type="var">eassumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">Hskip</span>. <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">edestruct</span> <span class="id" type="var">IHHpe2</span>. <span class="id" type="var">eassumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">econstructor</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">E_IfTrue</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">pe_bexp_correct</span>. <span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">repeat</span> <span class="id" type="tactic">eapply</span> <span class="id" type="var">E_Seq</span>; <span class="id" type="tactic">eauto</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">eval_assign</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> → <span class="id" type="var">pe_compare_update</span>, &lt;- <span class="id" type="var">assign_removes</span>. <span class="id" type="var">eassumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">omega</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;PE_WhileFixedLoop&nbsp;*)</span> <span class="id" type="var">exfalso</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">generalize</span> <span class="id" type="tactic">dependent</span> (<span class="id" type="var">S</span> (<span class="id" type="var">n<sub>1</sub></span> + <span class="id" type="var">n<sub>2</sub></span>)). <span class="id" type="tactic">intros</span> <span class="id" type="var">n</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">clear</span> - <span class="id" type="var">H</span> <span class="id" type="var">H<sub>0</sub></span> <span class="id" type="var">IHHpe1</span> <span class="id" type="var">IHHpe2</span>. <span class="id" type="tactic">generalize</span> <span class="id" type="tactic">dependent</span> <span class="id" type="var">st</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">induction</span> <span class="id" type="var">n</span> <span class="id" type="keyword">using</span> <span class="id" type="var">lt_wf_ind</span>; <span class="id" type="tactic">intros</span> <span class="id" type="var">st</span> <span class="id" type="var">Heval</span>. <span class="id" type="tactic">inversion</span> <span class="id" type="var">Heval</span>; <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;E'WhileFalse&nbsp;*)</span> <span class="id" type="tactic">rewrite</span> <span class="id" type="var">pe_bexp_correct</span>, <span class="id" type="var">H</span> <span class="id" type="keyword">in</span> <span class="id" type="var">H<sub>7</sub></span>. <span class="id" type="tactic">inversion</span> <span class="id" type="var">H<sub>7</sub></span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;E'WhileTrue&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">edestruct</span> <span class="id" type="var">IHHpe1</span> <span class="id" type="keyword">as</span> [? ? ? <span class="id" type="var">Hskip</span> ?]. <span class="id" type="var">eassumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">Hskip</span>. <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">edestruct</span> <span class="id" type="var">IHHpe2</span>. <span class="id" type="var">eassumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> &lt;- (<span class="id" type="var">pe_compare_nil_update</span> <span class="id" type="var">_</span> <span class="id" type="var">_</span> <span class="id" type="var">H<sub>0</sub></span>) <span class="id" type="keyword">in</span> <span class="id" type="var">H<sub>7</sub></span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">H<sub>1</sub></span> <span class="id" type="keyword">in</span> <span class="id" type="var">H<sub>7</sub></span>; [| <span class="id" type="tactic">omega</span>]. <span class="id" type="tactic">inversion</span> <span class="id" type="var">H<sub>7</sub></span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;PE_WhileFixed&nbsp;*)</span> <span class="id" type="tactic">generalize</span> <span class="id" type="tactic">dependent</span> <span class="id" type="var">st</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">induction</span> <span class="id" type="var">n</span> <span class="id" type="keyword">using</span> <span class="id" type="var">lt_wf_ind</span>; <span class="id" type="tactic">intros</span> <span class="id" type="var">st</span> <span class="id" type="var">Heval</span>. <span class="id" type="tactic">inversion</span> <span class="id" type="var">Heval</span>; <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;E'WhileFalse&nbsp;*)</span> <span class="id" type="tactic">rewrite</span> <span class="id" type="var">pe_bexp_correct</span> <span class="id" type="keyword">in</span> <span class="id" type="var">H<sub>8</sub></span>. <span class="id" type="tactic">eauto</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;E'WhileTrue&nbsp;*)</span> <span class="id" type="tactic">rewrite</span> <span class="id" type="var">pe_bexp_correct</span> <span class="id" type="keyword">in</span> <span class="id" type="var">H<sub>5</sub></span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">edestruct</span> <span class="id" type="var">IHHpe1</span> <span class="id" type="keyword">as</span> [? ? ? <span class="id" type="var">Hskip</span> ?]. <span class="id" type="var">eassumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">Hskip</span>. <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">edestruct</span> <span class="id" type="var">IHHpe2</span>. <span class="id" type="var">eassumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> &lt;- (<span class="id" type="var">pe_compare_nil_update</span> <span class="id" type="var">_</span> <span class="id" type="var">_</span> <span class="id" type="var">H<sub>1</sub></span>) <span class="id" type="keyword">in</span> <span class="id" type="var">H<sub>8</sub></span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">H<sub>2</sub></span> <span class="id" type="keyword">in</span> <span class="id" type="var">H<sub>8</sub></span>; [| <span class="id" type="tactic">omega</span>]. <span class="id" type="tactic">inversion</span> <span class="id" type="var">H<sub>8</sub></span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">econstructor</span>; [ <span class="id" type="tactic">eapply</span> <span class="id" type="var">E_WhileTrue</span>; <span class="id" type="tactic">eauto</span> | <span class="id" type="var">eassumption</span> | <span class="id" type="tactic">omega</span>].<br/>
<span class="id" type="keyword">Qed</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">pe_com_sound</span>:<br/>
&nbsp;&nbsp;<span style='font-size:120%;'>&forall;</span><span class="id" type="var">c</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">pe_st'</span> <span class="id" type="var">c'</span> <span class="id" type="var">c''</span>, <span class="id" type="var">c</span> / <span class="id" type="var">pe_st</span> \\ <span class="id" type="var">c'</span> / <span class="id" type="var">pe_st'</span> / <span class="id" type="var">c''</span> →<br/>
&nbsp;&nbsp;<span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">st''</span> <span class="id" type="var">n</span>,<br/>
&nbsp;&nbsp;(<span class="id" type="var">c'</span> / <span class="id" type="var">pe_st'</span> / <span class="id" type="var">c''</span> / <span class="id" type="var">st</span> \\ <span class="id" type="var">st''</span> # <span class="id" type="var">n</span>) →<br/>
&nbsp;&nbsp;(<span class="id" type="var">pe_update</span> <span class="id" type="var">st</span> <span class="id" type="var">pe_st</span> =[ <span class="id" type="var">c</span> ]⇒ <span class="id" type="var">st''</span>).<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">c</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">pe_st'</span> <span class="id" type="var">c'</span> <span class="id" type="var">c''</span> <span class="id" type="var">Hpe</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">induction</span> <span class="id" type="var">Hpe</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">st</span> <span class="id" type="var">st''</span> <span class="id" type="var">n</span> [<span class="id" type="var">st'</span> <span class="id" type="var">n'</span> <span class="id" type="var">Heval</span> <span class="id" type="var">Heval'</span> <span class="id" type="var">Hle</span>];<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">try</span> (<span class="id" type="tactic">inversion</span> <span class="id" type="var">Heval</span>; []; <span class="id" type="tactic">subst</span>);<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">try</span> (<span class="id" type="tactic">inversion</span> <span class="id" type="var">Heval'</span>; []; <span class="id" type="tactic">subst</span>); <span class="id" type="tactic">eauto</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;PE_AssStatic&nbsp;*)</span> <span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">pe_update_update_add</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">E_Ass</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> → <span class="id" type="var">pe_aexp_correct</span>. <span class="id" type="tactic">rewrite</span> → <span class="id" type="var">H</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;PE_AssDynamic&nbsp;*)</span> <span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">pe_update_update_remove</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">E_Ass</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">pe_aexp_correct</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;PE_Seq&nbsp;*)</span> <span class="id" type="tactic">eapply</span> <span class="id" type="var">E_Seq</span>; <span class="id" type="tactic">eauto</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;PE_IfTrue&nbsp;*)</span> <span class="id" type="tactic">apply</span> <span class="id" type="var">E_IfTrue</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> → <span class="id" type="var">pe_bexp_correct</span>. <span class="id" type="tactic">rewrite</span> → <span class="id" type="var">H</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">IHHpe</span>. <span class="id" type="tactic">eauto</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;PE_IfFalse&nbsp;*)</span> <span class="id" type="tactic">apply</span> <span class="id" type="var">E_IfFalse</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> → <span class="id" type="var">pe_bexp_correct</span>. <span class="id" type="tactic">rewrite</span> → <span class="id" type="var">H</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">IHHpe</span>. <span class="id" type="tactic">eauto</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;PE_If&nbsp;*)</span> <span class="id" type="tactic">inversion</span> <span class="id" type="var">Heval</span>; <span class="id" type="tactic">subst</span>; <span class="id" type="tactic">inversion</span> <span class="id" type="var">H<sub>7</sub></span>; <span class="id" type="tactic">subst</span>; <span class="id" type="tactic">clear</span> <span class="id" type="var">H<sub>7</sub></span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;E_IfTrue&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">ceval_deterministic</span> <span class="id" type="keyword">in</span> <span class="id" type="var">H<sub>8</sub></span>; [| <span class="id" type="tactic">apply</span> <span class="id" type="var">eval_assign</span>]. <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">assign_removes</span> <span class="id" type="keyword">in</span> <span class="id" type="var">Heval'</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">E_IfTrue</span>. <span class="id" type="tactic">rewrite</span> → <span class="id" type="var">pe_bexp_correct</span>. <span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">IHHpe1</span>. <span class="id" type="tactic">eauto</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;E_IfFalse&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">ceval_deterministic</span> <span class="id" type="keyword">in</span> <span class="id" type="var">H<sub>8</sub></span>; [| <span class="id" type="tactic">apply</span> <span class="id" type="var">eval_assign</span>]. <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> → <span class="id" type="var">pe_compare_update</span> <span class="id" type="keyword">in</span> <span class="id" type="var">Heval'</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">assign_removes</span> <span class="id" type="keyword">in</span> <span class="id" type="var">Heval'</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">E_IfFalse</span>. <span class="id" type="tactic">rewrite</span> → <span class="id" type="var">pe_bexp_correct</span>. <span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">IHHpe2</span>. <span class="id" type="tactic">eauto</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;PE_WhileFalse&nbsp;*)</span> <span class="id" type="tactic">apply</span> <span class="id" type="var">E_WhileFalse</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> → <span class="id" type="var">pe_bexp_correct</span>. <span class="id" type="tactic">rewrite</span> → <span class="id" type="var">H</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;PE_WhileTrue&nbsp;*)</span> <span class="id" type="tactic">eapply</span> <span class="id" type="var">E_WhileTrue</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> → <span class="id" type="var">pe_bexp_correct</span>. <span class="id" type="tactic">rewrite</span> → <span class="id" type="var">H</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">IHHpe1</span>. <span class="id" type="tactic">eauto</span>. <span class="id" type="tactic">eapply</span> <span class="id" type="var">IHHpe2</span>. <span class="id" type="tactic">eauto</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;PE_While&nbsp;*)</span> <span class="id" type="tactic">inversion</span> <span class="id" type="var">Heval</span>; <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;E_IfTrue&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">H<sub>9</sub></span>. <span class="id" type="tactic">subst</span>. <span class="id" type="tactic">clear</span> <span class="id" type="var">H<sub>9</sub></span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">H<sub>10</sub></span>. <span class="id" type="tactic">subst</span>. <span class="id" type="tactic">clear</span> <span class="id" type="var">H<sub>10</sub></span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">ceval_deterministic</span> <span class="id" type="keyword">in</span> <span class="id" type="var">H<sub>11</sub></span>; [| <span class="id" type="tactic">apply</span> <span class="id" type="var">eval_assign</span>]. <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> → <span class="id" type="var">pe_compare_update</span> <span class="id" type="keyword">in</span> <span class="id" type="var">Heval'</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">assign_removes</span> <span class="id" type="keyword">in</span> <span class="id" type="var">Heval'</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">E_WhileTrue</span>. <span class="id" type="tactic">rewrite</span> → <span class="id" type="var">pe_bexp_correct</span>. <span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">IHHpe1</span>. <span class="id" type="tactic">eauto</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">IHHpe2</span>. <span class="id" type="tactic">eauto</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;E_IfFalse&nbsp;*)</span> <span class="id" type="tactic">apply</span> <span class="id" type="var">ceval_count_sound</span> <span class="id" type="keyword">in</span> <span class="id" type="var">Heval'</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">ceval_deterministic</span> <span class="id" type="keyword">in</span> <span class="id" type="var">H<sub>9</sub></span>; [| <span class="id" type="tactic">apply</span> <span class="id" type="var">eval_assign</span>]. <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> &lt;- <span class="id" type="var">assign_removes</span> <span class="id" type="keyword">in</span> <span class="id" type="var">Heval'</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">H<sub>2</sub></span>; <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* <span class="comment">(*&nbsp;c<sub>2</sub>''&nbsp;=&nbsp;SKIP&nbsp;*)</span> <span class="id" type="tactic">inversion</span> <span class="id" type="var">Heval'</span>. <span class="id" type="tactic">subst</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">E_WhileFalse</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> → <span class="id" type="var">pe_bexp_correct</span>. <span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;* <span class="comment">(*&nbsp;c<sub>2</sub>''&nbsp;=&nbsp;WHILE&nbsp;b<sub>1</sub>&nbsp;DO&nbsp;c<sub>1</sub>&nbsp;END&nbsp;*)</span> <span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;PE_WhileFixedEnd&nbsp;*)</span> <span class="id" type="tactic">eapply</span> <span class="id" type="var">ceval_count_sound</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">Heval'</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;PE_WhileFixedLoop&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">loop_never_stops</span> <span class="id" type="keyword">in</span> <span class="id" type="var">Heval</span>. <span class="id" type="tactic">inversion</span> <span class="id" type="var">Heval</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;PE_WhileFixed&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">clear</span> - <span class="id" type="var">H<sub>1</sub></span> <span class="id" type="var">IHHpe1</span> <span class="id" type="var">IHHpe2</span> <span class="id" type="var">Heval</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">remember</span> (<span class="id" type="var">WHILE</span> <span class="id" type="var">pe_bexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">b<sub>1</sub></span> <span class="id" type="var">DO</span> <span class="id" type="var">c<sub>1</sub>'</span>;; <span class="id" type="var">c<sub>2</sub>'</span> <span class="id" type="var">END</span>)%<span class="id" type="var">imp</span> <span class="id" type="keyword">as</span> <span class="id" type="var">c'</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">induction</span> <span class="id" type="var">Heval</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">Heqc'</span>; <span class="id" type="tactic">subst</span>; <span class="id" type="tactic">clear</span> <span class="id" type="var">Heqc'</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;E_WhileFalse&nbsp;*)</span> <span class="id" type="tactic">apply</span> <span class="id" type="var">E_WhileFalse</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> <span class="id" type="var">pe_bexp_correct</span>. <span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;E_WhileTrue&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">assert</span> (<span class="id" type="var">IHHeval2'</span> := <span class="id" type="var">IHHeval2</span> (<span class="id" type="var">refl_equal</span> <span class="id" type="var">_</span>)).<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">ceval_count_complete</span> <span class="id" type="keyword">in</span> <span class="id" type="var">IHHeval2'</span>. <span class="id" type="tactic">inversion</span> <span class="id" type="var">IHHeval2'</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">clear</span> <span class="id" type="var">IHHeval1</span> <span class="id" type="var">IHHeval2</span> <span class="id" type="var">IHHeval2'</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">Heval1</span>. <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">E_WhileTrue</span>. <span class="id" type="tactic">rewrite</span> <span class="id" type="var">pe_bexp_correct</span>. <span class="id" type="tactic">assumption</span>. <span class="id" type="tactic">eauto</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">IHHpe2</span>. <span class="id" type="var">econstructor</span>. <span class="id" type="var">eassumption</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">rewrite</span> &lt;- (<span class="id" type="var">pe_compare_nil_update</span> <span class="id" type="var">_</span> <span class="id" type="var">_</span> <span class="id" type="var">H<sub>1</sub></span>). <span class="id" type="var">eassumption</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">le_n</span>.<br/>
<span class="id" type="keyword">Qed</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Corollary</span> <span class="id" type="var">pe_com_correct</span>:<br/>
&nbsp;&nbsp;<span style='font-size:120%;'>&forall;</span><span class="id" type="var">c</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">pe_st'</span> <span class="id" type="var">c'</span>, <span class="id" type="var">c</span> / <span class="id" type="var">pe_st</span> \\ <span class="id" type="var">c'</span> / <span class="id" type="var">pe_st'</span> / <span class="id" type="var">SKIP</span> →<br/>
&nbsp;&nbsp;<span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">st''</span>,<br/>
&nbsp;&nbsp;(<span class="id" type="var">pe_update</span> <span class="id" type="var">st</span> <span class="id" type="var">pe_st</span> =[ <span class="id" type="var">c</span> ]⇒ <span class="id" type="var">st''</span>) ↔<br/>
&nbsp;&nbsp;(<span style='font-size:120%;'>&exist;</span><span class="id" type="var">st'</span>, <span class="id" type="var">st</span> =[ <span class="id" type="var">c'</span> ]⇒ <span class="id" type="var">st'</span> ∧ <span class="id" type="var">pe_update</span> <span class="id" type="var">st'</span> <span class="id" type="var">pe_st'</span> = <span class="id" type="var">st''</span>).<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">c</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">pe_st'</span> <span class="id" type="var">c'</span> <span class="id" type="var">H</span> <span class="id" type="var">st</span> <span class="id" type="var">st''</span>. <span class="id" type="tactic">split</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;*)</span> <span class="id" type="tactic">intros</span> <span class="id" type="var">Heval</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">ceval_count_complete</span> <span class="id" type="keyword">in</span> <span class="id" type="var">Heval</span>. <span class="id" type="tactic">inversion</span> <span class="id" type="var">Heval</span> <span class="id" type="keyword">as</span> [<span class="id" type="var">n</span> <span class="id" type="var">Heval'</span>].<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">pe_com_complete</span> <span class="id" type="keyword">with</span> (<span class="id" type="var">st</span>:=<span class="id" type="var">st</span>) (<span class="id" type="var">st''</span>:=<span class="id" type="var">st''</span>) (<span class="id" type="var">n</span>:=<span class="id" type="var">n</span>) <span class="id" type="keyword">in</span> <span class="id" type="var">H</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span> <span class="id" type="keyword">as</span> [? ? ? <span class="id" type="var">Hskip</span> ?]. <span class="id" type="tactic">inversion</span> <span class="id" type="var">Hskip</span>. <span class="id" type="tactic">subst</span>. <span class="id" type="tactic">eauto</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">assumption</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;&lt;-&nbsp;*)</span> <span class="id" type="tactic">intros</span> [<span class="id" type="var">st'</span> [<span class="id" type="var">Heval</span> <span class="id" type="var">Heq</span>]]. <span class="id" type="tactic">subst</span> <span class="id" type="var">st''</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">pe_com_sound</span> <span class="id" type="keyword">in</span> <span class="id" type="var">H</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">H</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">econstructor</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">Heval</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">E'Skip</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">le_n</span>.<br/>
<span class="id" type="keyword">Qed</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">End</span> <span class="id" type="var">Loop</span>.<br/>
</div>

<div class="doc">
<a name="lab589"></a><h1 class="section">流程图程序的部分求值</h1>

<div class="paragraph"> </div>

 除了直接对 <span class="inlinecode"><span class="id" type="var">WHILE</span></span> 的循环直接进行部分求值，一种对命令式程序进行部分求值
    的标准方式是将他们转换为<b>流程图（Flowcharts）</b>。换句话说，为我们的语言
    添加标签和跳转会使部分求值更容易。流程图程序的部分求值结果是一个剩余流程图。
    幸运的话，剩余流程图程序中的跳转会被转换回 <span class="inlinecode"><span class="id" type="var">WHILE</span></span> 循环，但一般来说这可
    能不会发生；在这里我们并不追求达成这一点。
<div class="paragraph"> </div>

<a name="lab590"></a><h2 class="section">基本块</h2>

<div class="paragraph"> </div>

 一个流程图程序由<b>基本块（basic blocks）</b>构成，我们用归纳类型 <span class="inlinecode"><span class="id" type="var">block</span></span>
    来表示它。一个基本块是一个赋值语句（<span class="inlinecode"><span class="id" type="var">Assign</span></span> 构造子）序列，并以条件跳转（<span class="inlinecode"><span class="id" type="var">If</span></span>
    构造子）或者无条件跳转（<span class="inlinecode"><span class="id" type="var">Goto</span></span> 构造子）结束。跳转的目标由<b>标签（labels）</b>所指明，
    其可为任意类型。因此，我们用标签的类型来参数化 <span class="inlinecode"><span class="id" type="var">block</span></span> 类型。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Inductive</span> <span class="id" type="var">block</span> (<span class="id" type="var">Label</span>:<span class="id" type="keyword">Type</span>) : <span class="id" type="keyword">Type</span> :=<br/>
&nbsp;&nbsp;| <span class="id" type="var">Goto</span> : <span class="id" type="var">Label</span> → <span class="id" type="var">block</span> <span class="id" type="var">Label</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">If</span> : <span class="id" type="var">bexp</span> → <span class="id" type="var">Label</span> → <span class="id" type="var">Label</span> → <span class="id" type="var">block</span> <span class="id" type="var">Label</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">Assign</span> : <span class="id" type="var">string</span> → <span class="id" type="var">aexp</span> → <span class="id" type="var">block</span> <span class="id" type="var">Label</span> → <span class="id" type="var">block</span> <span class="id" type="var">Label</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="var">Arguments</span> <span class="id" type="var">Goto</span> {<span class="id" type="var">Label</span>} <span class="id" type="var">_</span>.<br/>
<span class="id" type="var">Arguments</span> <span class="id" type="var">If</span>   {<span class="id" type="var">Label</span>} <span class="id" type="var">_</span> <span class="id" type="var">_</span> <span class="id" type="var">_</span>.<br/>
<span class="id" type="var">Arguments</span> <span class="id" type="var">Assign</span> {<span class="id" type="var">Label</span>} <span class="id" type="var">_</span> <span class="id" type="var">_</span> <span class="id" type="var">_</span>.<br/>
</div>

<div class="doc">
我们用上面 Imp 的“奇或偶”程序作为例子。将这个程序转换为流程图程序需要 4
    个标签，因此我们定义如下类型。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Inductive</span> <span class="id" type="var">parity_label</span> : <span class="id" type="keyword">Type</span> :=<br/>
&nbsp;&nbsp;| <span class="id" type="var">entry</span> : <span class="id" type="var">parity_label</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">loop</span>  : <span class="id" type="var">parity_label</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">body</span>  : <span class="id" type="var">parity_label</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">done</span>  : <span class="id" type="var">parity_label</span>.<br/>
</div>

<div class="doc">
下面的 <span class="inlinecode"><span class="id" type="var">block</span></span> 是一个基本块，构成了例子程序的 <span class="inlinecode"><span class="id" type="var">body</span></span> 标签所代表的基本块。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Definition</span> <span class="id" type="var">parity_body</span> : <span class="id" type="var">block</span> <span class="id" type="var">parity_label</span> :=<br/>
&nbsp;&nbsp;<span class="id" type="var">Assign</span> <span class="id" type="var">Y</span> (<span class="id" type="var">Y</span> - 1)<br/>
&nbsp;&nbsp;&nbsp;(<span class="id" type="var">Assign</span> <span class="id" type="var">X</span> (1 - <span class="id" type="var">X</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<span class="id" type="var">Goto</span> <span class="id" type="var">loop</span>)).<br/>
</div>

<div class="doc">
给定一个初始状态，对基本块的求值是计算出最终状态和跳转的目标标签。
    由于基本块不包含循环或其他控制结构，对基本块的求值是一个全函数——我们不需要
    担心非停机性。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Fixpoint</span> <span class="id" type="var">keval</span> {<span class="id" type="var">L</span>:<span class="id" type="keyword">Type</span>} (<span class="id" type="var">st</span>:<span class="id" type="var">state</span>) (<span class="id" type="var">k</span> : <span class="id" type="var">block</span> <span class="id" type="var">L</span>) : <span class="id" type="var">state</span> * <span class="id" type="var">L</span> :=<br/>
&nbsp;&nbsp;<span class="id" type="keyword">match</span> <span class="id" type="var">k</span> <span class="id" type="keyword">with</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">Goto</span> <span class="id" type="var">l</span> ⇒ (<span class="id" type="var">st</span>, <span class="id" type="var">l</span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">If</span> <span class="id" type="var">b</span> <span class="id" type="var">l<sub>1</sub></span> <span class="id" type="var">l<sub>2</sub></span> ⇒ (<span class="id" type="var">st</span>, <span class="id" type="keyword">if</span> <span class="id" type="var">beval</span> <span class="id" type="var">st</span> <span class="id" type="var">b</span> <span class="id" type="keyword">then</span> <span class="id" type="var">l<sub>1</sub></span> <span class="id" type="keyword">else</span> <span class="id" type="var">l<sub>2</sub></span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">Assign</span> <span class="id" type="var">i</span> <span class="id" type="var">a</span> <span class="id" type="var">k</span> ⇒ <span class="id" type="var">keval</span> (<span class="id" type="var">t_update</span> <span class="id" type="var">st</span> <span class="id" type="var">i</span> (<span class="id" type="var">aeval</span> <span class="id" type="var">st</span> <span class="id" type="var">a</span>)) <span class="id" type="var">k</span><br/>
&nbsp;&nbsp;<span class="id" type="keyword">end</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">keval_example</span>:<br/>
&nbsp;&nbsp;<span class="id" type="var">keval</span> <span class="id" type="var">empty_st</span> <span class="id" type="var">parity_body</span><br/>
&nbsp;&nbsp;= ((<span class="id" type="var">X</span> !<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> 1 ; <span class="id" type="var">Y</span> !<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span> 0), <span class="id" type="var">loop</span>).<br/>
<div class="togglescript" id="proofcontrol5" onclick="toggleDisplay('proof5');toggleDisplay('proofcontrol5')"><span class="show"></span></div>
<div class="proofscript" id="proof5" onclick="toggleDisplay('proof5');toggleDisplay('proofcontrol5')">
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">reflexivity</span>. <span class="id" type="keyword">Qed</span>.<br/>
</div>
</div>

<div class="doc">
<a name="lab591"></a><h2 class="section">流程图程序</h2>

<div class="paragraph"> </div>

 一个流程图程序是一个查找函数将标签映射到基本块。事实上，有的标签是
    <b>停机状态（halting state）</b>并且不被映射到任何基本块。因此准确地说，一个
    流程图程序 <span class="inlinecode"><span class="id" type="var">program</span></span> 是一个将 <span class="inlinecode"><span class="id" type="var">L</span></span> 映射到到 <span class="inlinecode"><span class="id" type="var">option</span></span> <span class="inlinecode">(<span class="id" type="var">block</span></span> <span class="inlinecode"><span class="id" type="var">L</span>)</span>
    的函数，其中 <span class="inlinecode"><span class="id" type="var">L</span></span> 是标签的类型。 
</div>
<div class="code code-tight">

<span class="id" type="keyword">Definition</span> <span class="id" type="var">program</span> (<span class="id" type="var">L</span>:<span class="id" type="keyword">Type</span>) : <span class="id" type="keyword">Type</span> := <span class="id" type="var">L</span> → <span class="id" type="var">option</span> (<span class="id" type="var">block</span> <span class="id" type="var">L</span>).<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Definition</span> <span class="id" type="var">parity</span> : <span class="id" type="var">program</span> <span class="id" type="var">parity_label</span> := <span class="id" type="keyword">fun</span> <span class="id" type="var">l</span> ⇒<br/>
&nbsp;&nbsp;<span class="id" type="keyword">match</span> <span class="id" type="var">l</span> <span class="id" type="keyword">with</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">entry</span> ⇒ <span class="id" type="var">Some</span> (<span class="id" type="var">Assign</span> <span class="id" type="var">X</span> 0 (<span class="id" type="var">Goto</span> <span class="id" type="var">loop</span>))<br/>
&nbsp;&nbsp;| <span class="id" type="var">loop</span> ⇒ <span class="id" type="var">Some</span> (<span class="id" type="var">If</span> (1 ≤ <span class="id" type="var">Y</span>) <span class="id" type="var">body</span> <span class="id" type="var">done</span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">body</span> ⇒ <span class="id" type="var">Some</span> <span class="id" type="var">parity_body</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">done</span> ⇒ <span class="id" type="var">None</span> <span class="comment">(*&nbsp;halt&nbsp;*)</span><br/>
&nbsp;&nbsp;<span class="id" type="keyword">end</span>.<br/>
</div>

<div class="doc">
不同与基本块，一个程序可能不会终止，因此我们把程序的求值建模为归纳关系 <span class="inlinecode"><span class="id" type="var">peval</span></span>
    而非递归函数。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Inductive</span> <span class="id" type="var">peval</span> {<span class="id" type="var">L</span>:<span class="id" type="keyword">Type</span>} (<span class="id" type="var">p</span> : <span class="id" type="var">program</span> <span class="id" type="var">L</span>)<br/>
&nbsp;&nbsp;: <span class="id" type="var">state</span> → <span class="id" type="var">L</span> → <span class="id" type="var">state</span> → <span class="id" type="var">L</span> → <span class="id" type="keyword">Prop</span> :=<br/>
&nbsp;&nbsp;| <span class="id" type="var">E_None</span>: <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">l</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">p</span> <span class="id" type="var">l</span> = <span class="id" type="var">None</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">peval</span> <span class="id" type="var">p</span> <span class="id" type="var">st</span> <span class="id" type="var">l</span> <span class="id" type="var">st</span> <span class="id" type="var">l</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">E_Some</span>: <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st</span> <span class="id" type="var">l</span> <span class="id" type="var">k</span> <span class="id" type="var">st'</span> <span class="id" type="var">l'</span> <span class="id" type="var">st''</span> <span class="id" type="var">l''</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">p</span> <span class="id" type="var">l</span> = <span class="id" type="var">Some</span> <span class="id" type="var">k</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">keval</span> <span class="id" type="var">st</span> <span class="id" type="var">k</span> = (<span class="id" type="var">st'</span>, <span class="id" type="var">l'</span>) →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">peval</span> <span class="id" type="var">p</span> <span class="id" type="var">st'</span> <span class="id" type="var">l'</span> <span class="id" type="var">st''</span> <span class="id" type="var">l''</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">peval</span> <span class="id" type="var">p</span> <span class="id" type="var">st</span> <span class="id" type="var">l</span> <span class="id" type="var">st''</span> <span class="id" type="var">l''</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">parity_eval</span>: <span class="id" type="var">peval</span> <span class="id" type="var">parity</span> <span class="id" type="var">empty_st</span> <span class="id" type="var">entry</span>  <span class="id" type="var">empty_st</span> <span class="id" type="var">done</span>.<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="var">erewrite</span> <span class="id" type="tactic">f_equal</span> <span class="id" type="keyword">with</span> (<span class="id" type="var">f</span> := <span class="id" type="keyword">fun</span> <span class="id" type="var">st</span> ⇒ <span class="id" type="var">peval</span> <span class="id" type="var">_</span> <span class="id" type="var">_</span> <span class="id" type="var">_</span> <span class="id" type="var">st</span> <span class="id" type="var">_</span>).<br/>
&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">E_Some</span>. <span class="id" type="tactic">reflexivity</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">E_Some</span>. <span class="id" type="tactic">reflexivity</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">E_None</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">apply</span> <span class="id" type="var">functional_extensionality</span>. <span class="id" type="tactic">intros</span> <span class="id" type="var">i</span>. <span class="id" type="tactic">rewrite</span> <span class="id" type="var">t_update_same</span>; <span class="id" type="tactic">auto</span>.<br/>
<span class="id" type="keyword">Qed</span>.<br/>
</div>

<div class="doc">
<a name="lab592"></a><h2 class="section">基本块和流程图程序的部分求值</h2>

<div class="paragraph"> </div>

 部分求值系统地改变了标签类型：如果标签类型是 <span class="inlinecode"><span class="id" type="var">L</span></span>，那么它会变为 <span class="inlinecode"><span class="id" type="var">pe_state</span></span> <span class="inlinecode">*</span> <span class="inlinecode"><span class="id" type="var">L</span></span>。
    因此源程序中的同同一个标签可能会未折叠、或展开多次，成为多个标签并和不同的部分状态配
    对在一起。比如说，<span class="inlinecode"><span class="id" type="var">parity</span></span> 程序中的 <span class="inlinecode"><span class="id" type="var">loop</span></span> 标签会变为两个标签：<span class="inlinecode">([(<span class="id" type="var">X</span>,0)],</span> <span class="inlinecode"><span class="id" type="var">loop</span>)</span>
    和 <span class="inlinecode">([(<span class="id" type="var">X</span>,1)],</span> <span class="inlinecode"><span class="id" type="var">loop</span>)</span>。标签类型的改变也在下面定义的 <span class="inlinecode"><span class="id" type="var">pe_block</span></span> 和 <span class="inlinecode"><span class="id" type="var">pe_program</span></span>
    的类型中反映出来。
</div>
<div class="code code-tight">

<span class="id" type="keyword">Fixpoint</span> <span class="id" type="var">pe_block</span> {<span class="id" type="var">L</span>:<span class="id" type="keyword">Type</span>} (<span class="id" type="var">pe_st</span>:<span class="id" type="var">pe_state</span>) (<span class="id" type="var">k</span> : <span class="id" type="var">block</span> <span class="id" type="var">L</span>)<br/>
&nbsp;&nbsp;: <span class="id" type="var">block</span> (<span class="id" type="var">pe_state</span> * <span class="id" type="var">L</span>) :=<br/>
&nbsp;&nbsp;<span class="id" type="keyword">match</span> <span class="id" type="var">k</span> <span class="id" type="keyword">with</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">Goto</span> <span class="id" type="var">l</span> ⇒ <span class="id" type="var">Goto</span> (<span class="id" type="var">pe_st</span>, <span class="id" type="var">l</span>)<br/>
&nbsp;&nbsp;| <span class="id" type="var">If</span> <span class="id" type="var">b</span> <span class="id" type="var">l<sub>1</sub></span> <span class="id" type="var">l<sub>2</sub></span> ⇒<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">match</span> <span class="id" type="var">pe_bexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">b</span> <span class="id" type="keyword">with</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;| <span class="id" type="var">BTrue</span>  ⇒ <span class="id" type="var">Goto</span> (<span class="id" type="var">pe_st</span>, <span class="id" type="var">l<sub>1</sub></span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;| <span class="id" type="var">BFalse</span> ⇒ <span class="id" type="var">Goto</span> (<span class="id" type="var">pe_st</span>, <span class="id" type="var">l<sub>2</sub></span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;| <span class="id" type="var">b'</span>     ⇒ <span class="id" type="var">If</span> <span class="id" type="var">b'</span> (<span class="id" type="var">pe_st</span>, <span class="id" type="var">l<sub>1</sub></span>) (<span class="id" type="var">pe_st</span>, <span class="id" type="var">l<sub>2</sub></span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">end</span><br/>
&nbsp;&nbsp;| <span class="id" type="var">Assign</span> <span class="id" type="var">i</span> <span class="id" type="var">a</span> <span class="id" type="var">k</span> ⇒<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">match</span> <span class="id" type="var">pe_aexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">a</span> <span class="id" type="keyword">with</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;| <span class="id" type="var">ANum</span> <span class="id" type="var">n</span> ⇒ <span class="id" type="var">pe_block</span> (<span class="id" type="var">pe_add</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">i</span> <span class="id" type="var">n</span>) <span class="id" type="var">k</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;| <span class="id" type="var">a'</span> ⇒ <span class="id" type="var">Assign</span> <span class="id" type="var">i</span> <span class="id" type="var">a'</span> (<span class="id" type="var">pe_block</span> (<span class="id" type="var">pe_remove</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">i</span>) <span class="id" type="var">k</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">end</span><br/>
&nbsp;&nbsp;<span class="id" type="keyword">end</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Example</span> <span class="id" type="var">pe_block_example</span>:<br/>
&nbsp;&nbsp;<span class="id" type="var">pe_block</span> [(<span class="id" type="var">X</span>,0)] <span class="id" type="var">parity_body</span><br/>
&nbsp;&nbsp;= <span class="id" type="var">Assign</span> <span class="id" type="var">Y</span> (<span class="id" type="var">Y</span> - 1) (<span class="id" type="var">Goto</span> ([(<span class="id" type="var">X</span>,1)], <span class="id" type="var">loop</span>)).<br/>
<div class="togglescript" id="proofcontrol6" onclick="toggleDisplay('proof6');toggleDisplay('proofcontrol6')"><span class="show"></span></div>
<div class="proofscript" id="proof6" onclick="toggleDisplay('proof6');toggleDisplay('proofcontrol6')">
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">reflexivity</span>. <span class="id" type="keyword">Qed</span>.<br/>
</div>

<br/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">pe_block_correct</span>: <span style='font-size:120%;'>&forall;</span>(<span class="id" type="var">L</span>:<span class="id" type="keyword">Type</span>) <span class="id" type="var">st</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">k</span> <span class="id" type="var">st'</span> <span class="id" type="var">pe_st'</span> (<span class="id" type="var">l'</span>:<span class="id" type="var">L</span>),<br/>
&nbsp;&nbsp;<span class="id" type="var">keval</span> <span class="id" type="var">st</span> (<span class="id" type="var">pe_block</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">k</span>) = (<span class="id" type="var">st'</span>, (<span class="id" type="var">pe_st'</span>, <span class="id" type="var">l'</span>)) →<br/>
&nbsp;&nbsp;<span class="id" type="var">keval</span> (<span class="id" type="var">pe_update</span> <span class="id" type="var">st</span> <span class="id" type="var">pe_st</span>) <span class="id" type="var">k</span> = (<span class="id" type="var">pe_update</span> <span class="id" type="var">st'</span> <span class="id" type="var">pe_st'</span>, <span class="id" type="var">l'</span>).<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">intros</span>. <span class="id" type="tactic">generalize</span> <span class="id" type="tactic">dependent</span> <span class="id" type="var">pe_st</span>. <span class="id" type="tactic">generalize</span> <span class="id" type="tactic">dependent</span> <span class="id" type="var">st</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">induction</span> <span class="id" type="var">k</span> <span class="id" type="keyword">as</span> [<span class="id" type="var">l</span> | <span class="id" type="var">b</span> <span class="id" type="var">l<sub>1</sub></span> <span class="id" type="var">l<sub>2</sub></span> | <span class="id" type="var">i</span> <span class="id" type="var">a</span> <span class="id" type="var">k</span>];<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">st</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">H</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;Goto&nbsp;*)</span> <span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span>; <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;If&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">replace</span> (<span class="id" type="var">keval</span> <span class="id" type="var">st</span> (<span class="id" type="var">pe_block</span> <span class="id" type="var">pe_st</span> (<span class="id" type="var">If</span> <span class="id" type="var">b</span> <span class="id" type="var">l<sub>1</sub></span> <span class="id" type="var">l<sub>2</sub></span>)))<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">with</span> (<span class="id" type="var">keval</span> <span class="id" type="var">st</span> (<span class="id" type="var">If</span> (<span class="id" type="var">pe_bexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">b</span>) (<span class="id" type="var">pe_st</span>, <span class="id" type="var">l<sub>1</sub></span>) (<span class="id" type="var">pe_st</span>, <span class="id" type="var">l<sub>2</sub></span>)))<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">in</span> <span class="id" type="var">H</span> <span class="id" type="tactic">by</span> (<span class="id" type="tactic">simpl</span>; <span class="id" type="tactic">destruct</span> (<span class="id" type="var">pe_bexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">b</span>); <span class="id" type="tactic">reflexivity</span>).<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">simpl</span> <span class="id" type="keyword">in</span> *. <span class="id" type="tactic">rewrite</span> <span class="id" type="var">pe_bexp_correct</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">beval</span> <span class="id" type="var">st</span> (<span class="id" type="var">pe_bexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">b</span>)); <span class="id" type="tactic">inversion</span> <span class="id" type="var">H</span>; <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;Assign&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">simpl</span> <span class="id" type="keyword">in</span> *. <span class="id" type="tactic">rewrite</span> <span class="id" type="var">pe_aexp_correct</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">pe_aexp</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">a</span>); <span class="id" type="tactic">simpl</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">try</span> <span class="id" type="var">solve</span> [<span class="id" type="tactic">rewrite</span> <span class="id" type="var">pe_update_update_add</span>; <span class="id" type="tactic">apply</span> <span class="id" type="var">IHk</span>; <span class="id" type="tactic">apply</span> <span class="id" type="var">H</span>];<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">solve</span> [<span class="id" type="tactic">rewrite</span> <span class="id" type="var">pe_update_update_remove</span>; <span class="id" type="tactic">apply</span> <span class="id" type="var">IHk</span>; <span class="id" type="tactic">apply</span> <span class="id" type="var">H</span>].<br/>
<span class="id" type="keyword">Qed</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Definition</span> <span class="id" type="var">pe_program</span> {<span class="id" type="var">L</span>:<span class="id" type="keyword">Type</span>} (<span class="id" type="var">p</span> : <span class="id" type="var">program</span> <span class="id" type="var">L</span>)<br/>
&nbsp;&nbsp;: <span class="id" type="var">program</span> (<span class="id" type="var">pe_state</span> * <span class="id" type="var">L</span>) :=<br/>
&nbsp;&nbsp;<span class="id" type="keyword">fun</span> <span class="id" type="var">pe_l</span> ⇒ <span class="id" type="keyword">match</span> <span class="id" type="var">pe_l</span> <span class="id" type="keyword">with</span> | (<span class="id" type="var">pe_st</span>, <span class="id" type="var">l</span>) ⇒<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">option_map</span> (<span class="id" type="var">pe_block</span> <span class="id" type="var">pe_st</span>) (<span class="id" type="var">p</span> <span class="id" type="var">l</span>)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="keyword">end</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Inductive</span> <span class="id" type="var">pe_peval</span> {<span class="id" type="var">L</span>:<span class="id" type="keyword">Type</span>} (<span class="id" type="var">p</span> : <span class="id" type="var">program</span> <span class="id" type="var">L</span>)<br/>
&nbsp;&nbsp;(<span class="id" type="var">st</span>:<span class="id" type="var">state</span>) (<span class="id" type="var">pe_st</span>:<span class="id" type="var">pe_state</span>) (<span class="id" type="var">l</span>:<span class="id" type="var">L</span>) (<span class="id" type="var">st'o</span>:<span class="id" type="var">state</span>) (<span class="id" type="var">l'</span>:<span class="id" type="var">L</span>) : <span class="id" type="keyword">Prop</span> :=<br/>
&nbsp;&nbsp;| <span class="id" type="var">pe_peval_intro</span> : <span style='font-size:120%;'>&forall;</span><span class="id" type="var">st'</span> <span class="id" type="var">pe_st'</span>,<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">peval</span> (<span class="id" type="var">pe_program</span> <span class="id" type="var">p</span>) <span class="id" type="var">st</span> (<span class="id" type="var">pe_st</span>, <span class="id" type="var">l</span>) <span class="id" type="var">st'</span> (<span class="id" type="var">pe_st'</span>, <span class="id" type="var">l'</span>) →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">pe_update</span> <span class="id" type="var">st'</span> <span class="id" type="var">pe_st'</span> = <span class="id" type="var">st'o</span> →<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">pe_peval</span> <span class="id" type="var">p</span> <span class="id" type="var">st</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">l</span> <span class="id" type="var">st'o</span> <span class="id" type="var">l'</span>.<br/><hr class='doublespaceincode'/>
<span class="id" type="keyword">Theorem</span> <span class="id" type="var">pe_program_correct</span>:<br/>
&nbsp;&nbsp;<span style='font-size:120%;'>&forall;</span>(<span class="id" type="var">L</span>:<span class="id" type="keyword">Type</span>) (<span class="id" type="var">p</span> : <span class="id" type="var">program</span> <span class="id" type="var">L</span>) <span class="id" type="var">st</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">l</span> <span class="id" type="var">st'o</span> <span class="id" type="var">l'</span>,<br/>
&nbsp;&nbsp;<span class="id" type="var">peval</span> <span class="id" type="var">p</span> (<span class="id" type="var">pe_update</span> <span class="id" type="var">st</span> <span class="id" type="var">pe_st</span>) <span class="id" type="var">l</span> <span class="id" type="var">st'o</span> <span class="id" type="var">l'</span> ↔<br/>
&nbsp;&nbsp;<span class="id" type="var">pe_peval</span> <span class="id" type="var">p</span> <span class="id" type="var">st</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">l</span> <span class="id" type="var">st'o</span> <span class="id" type="var">l'</span>.<br/>
<span class="id" type="keyword">Proof</span>. <span class="id" type="tactic">intros</span>.<br/>
&nbsp;&nbsp;<span class="id" type="tactic">split</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;<span class="nowrap"><span style='font-size:85%;'><span style='vertical-align:5%;'><span style='letter-spacing:-.2em;'>-</span></span>&gt;</span></span>&nbsp;*)</span> <span class="id" type="tactic">intros</span> <span class="id" type="var">Heval</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">remember</span> (<span class="id" type="var">pe_update</span> <span class="id" type="var">st</span> <span class="id" type="var">pe_st</span>) <span class="id" type="keyword">as</span> <span class="id" type="var">sto</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">generalize</span> <span class="id" type="tactic">dependent</span> <span class="id" type="var">pe_st</span>. <span class="id" type="tactic">generalize</span> <span class="id" type="tactic">dependent</span> <span class="id" type="var">st</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">induction</span> <span class="id" type="var">Heval</span> <span class="id" type="keyword">as</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[ <span class="id" type="var">sto</span> <span class="id" type="var">l</span> <span class="id" type="var">Hlookup</span> | <span class="id" type="var">sto</span> <span class="id" type="var">l</span> <span class="id" type="var">k</span> <span class="id" type="var">st'o</span> <span class="id" type="var">l'</span> <span class="id" type="var">st''o</span> <span class="id" type="var">l''</span> <span class="id" type="var">Hlookup</span> <span class="id" type="var">Hkeval</span> <span class="id" type="var">Heval</span> ];<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">st</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">Heqsto</span>; <span class="id" type="tactic">subst</span> <span class="id" type="var">sto</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;E_None&nbsp;*)</span> <span class="id" type="tactic">eapply</span> <span class="id" type="var">pe_peval_intro</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">E_None</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">simpl</span>. <span class="id" type="tactic">rewrite</span> <span class="id" type="var">Hlookup</span>. <span class="id" type="tactic">reflexivity</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;E_Some&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">remember</span> (<span class="id" type="var">keval</span> <span class="id" type="var">st</span> (<span class="id" type="var">pe_block</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">k</span>)) <span class="id" type="keyword">as</span> <span class="id" type="var">x</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> <span class="id" type="var">x</span> <span class="id" type="keyword">as</span> [<span class="id" type="var">st'</span> [<span class="id" type="var">pe_st'</span> <span class="id" type="var">l'_</span>]].<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">symmetry</span> <span class="id" type="keyword">in</span> <span class="id" type="var">Heqx</span>. <span class="id" type="var">erewrite</span> <span class="id" type="var">pe_block_correct</span> <span class="id" type="keyword">in</span> <span class="id" type="var">Hkeval</span> <span class="id" type="tactic">by</span> <span class="id" type="tactic">apply</span> <span class="id" type="var">Heqx</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">Hkeval</span>. <span class="id" type="tactic">subst</span> <span class="id" type="var">st'o</span> <span class="id" type="var">l'_</span>. <span class="id" type="tactic">clear</span> <span class="id" type="var">Hkeval</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">edestruct</span> <span class="id" type="var">IHHeval</span>. <span class="id" type="tactic">reflexivity</span>. <span class="id" type="tactic">subst</span> <span class="id" type="var">st''o</span>. <span class="id" type="tactic">clear</span> <span class="id" type="var">IHHeval</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">pe_peval_intro</span>; [| <span class="id" type="tactic">reflexivity</span>]. <span class="id" type="tactic">eapply</span> <span class="id" type="var">E_Some</span>; <span class="id" type="tactic">eauto</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">simpl</span>. <span class="id" type="tactic">rewrite</span> <span class="id" type="var">Hlookup</span>. <span class="id" type="tactic">reflexivity</span>.<br/>
&nbsp;&nbsp;- <span class="comment">(*&nbsp;&lt;-&nbsp;*)</span> <span class="id" type="tactic">intros</span> [<span class="id" type="var">st'</span> <span class="id" type="var">pe_st'</span> <span class="id" type="var">Heval</span> <span class="id" type="var">Heqst'o</span>].<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">remember</span> (<span class="id" type="var">pe_st</span>, <span class="id" type="var">l</span>) <span class="id" type="keyword">as</span> <span class="id" type="var">pe_st_l</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">remember</span> (<span class="id" type="var">pe_st'</span>, <span class="id" type="var">l'</span>) <span class="id" type="keyword">as</span> <span class="id" type="var">pe_st'_l'</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">generalize</span> <span class="id" type="tactic">dependent</span> <span class="id" type="var">pe_st</span>. <span class="id" type="tactic">generalize</span> <span class="id" type="tactic">dependent</span> <span class="id" type="var">l</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">induction</span> <span class="id" type="var">Heval</span> <span class="id" type="keyword">as</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[ <span class="id" type="var">st</span> [<span class="id" type="var">pe_st_</span> <span class="id" type="var">l_</span>] <span class="id" type="var">Hlookup</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| <span class="id" type="var">st</span> [<span class="id" type="var">pe_st_</span> <span class="id" type="var">l_</span>] <span class="id" type="var">pe_k</span> <span class="id" type="var">st'</span> [<span class="id" type="var">pe_st'_</span> <span class="id" type="var">l'_</span>] <span class="id" type="var">st''</span> [<span class="id" type="var">pe_st''</span> <span class="id" type="var">l''</span>]<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="var">Hlookup</span> <span class="id" type="var">Hkeval</span> <span class="id" type="var">Heval</span> ];<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">intros</span> <span class="id" type="var">l</span> <span class="id" type="var">pe_st</span> <span class="id" type="var">Heqpe_st_l</span>;<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">inversion</span> <span class="id" type="var">Heqpe_st_l</span>; <span class="id" type="tactic">inversion</span> <span class="id" type="var">Heqpe_st'_l'</span>; <span class="id" type="tactic">repeat</span> <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;E_None&nbsp;*)</span> <span class="id" type="tactic">apply</span> <span class="id" type="var">E_None</span>. <span class="id" type="tactic">simpl</span> <span class="id" type="keyword">in</span> <span class="id" type="var">Hlookup</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> (<span class="id" type="var">p</span> <span class="id" type="var">l'</span>); [ <span class="id" type="var">solve</span> [ <span class="id" type="tactic">inversion</span> <span class="id" type="var">Hlookup</span> ] | <span class="id" type="tactic">reflexivity</span> ].<br/>
&nbsp;&nbsp;&nbsp;&nbsp;+ <span class="comment">(*&nbsp;E_Some&nbsp;*)</span><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">simpl</span> <span class="id" type="keyword">in</span> <span class="id" type="var">Hlookup</span>. <span class="id" type="var">remember</span> (<span class="id" type="var">p</span> <span class="id" type="var">l</span>) <span class="id" type="keyword">as</span> <span class="id" type="var">k</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">destruct</span> <span class="id" type="var">k</span> <span class="id" type="keyword">as</span> [<span class="id" type="var">k</span>|]; <span class="id" type="tactic">inversion</span> <span class="id" type="var">Hlookup</span>; <span class="id" type="tactic">subst</span>.<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="id" type="tactic">eapply</span> <span class="id" type="var">E_Some</span>; <span class="id" type="tactic">eauto</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">pe_block_correct</span>. <span class="id" type="tactic">apply</span> <span class="id" type="var">Hkeval</span>.<br/>
<span class="id" type="keyword">Qed</span>.<br/><hr class='doublespaceincode'/>
<span class="comment">(*&nbsp;Mon&nbsp;Oct&nbsp;28&nbsp;08:15:21&nbsp;UTC&nbsp;2019&nbsp;*)</span><br/>
</div>
</div>



</div>

</body>
</html>